Python 3에서 True와 False의 다른 객체 크기
__sizeof__
다른 Python 객체에서 (특히) 매직 메서드를 실험하면서 다음 동작을 발견했습니다.
파이썬 2.7
>>> False.__sizeof__()
24
>>> True.__sizeof__()
24
Python 3.x
>>> False.__sizeof__()
24
>>> True.__sizeof__()
28
크기를 크기 True
보다 크게 만드는 Python 3에서 변경된 사항은 무엇입니까 False
?
왜냐하면 파이썬 2와 3 모두 bool
의 하위 클래스 이기 때문 입니다 int
.
>>> issubclass(bool, int)
True
그러나 int
구현이 변경되었습니다.
Python 2에서는 int
임의의 길이가 아닌 시스템에 따라 32 비트 또는 64 비트였습니다 long
.
Python 3에서는 int
임의 길이 long
입니다. Python 2의 이름이로 변경되고 int
원래 Python 2 int
가 완전히 삭제되었습니다.
파이썬 2에서 당신의 정확히 같은 동작 얻을 긴 개체 1L
및 0L
:
Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getsizeof(1L)
28
>>> sys.getsizeof(0L)
24
long
/ 파이썬 3 int
단지 튜플처럼, 가변 길이 개체입니다 -이 할당 될 때, 충분한 메모리가 그것을 표현하는 데 필요한 모든 이진수를 개최 할당됩니다. 가변 부분의 길이는 오브젝트 헤드에 저장됩니다. 0
이진 숫자는 필요하지 않지만 (변수 길이는 0 임) 1
넘쳐나고 추가 숫자가 필요합니다.
즉 0
, 길이가 0 인 2 진 문자열로 표시됩니다.
<>
1은 30 비트 이진 문자열로 표시됩니다.
<000000000000000000000000000001>
Python의 기본 구성 은 auint32_t
; so 2**30 - 1
x86-64에서 여전히 28 바이트에 맞으며 2**30
32가 필요합니다.
2**30 - 1
다음과 같이 표시됩니다.
<111111111111111111111111111111>
즉, 모든 30 값 비트는 1로 설정됩니다. 2 ** 30은 더 많이 필요하며 내부 표현을 갖습니다.
<000000000000000000000000000001000000000000000000000000000000>
24 대신 28 바이트 를 True
사용하는 경우 걱정할 필요가 없습니다. 은 싱글 톤 이므로 모든 Python 프로그램 에서 총 4 바이트 만 손실되며 .True
True
둘 다 True
하고 False
있습니다 longobject
의 CPython의의는 :
struct _longobject _Py_FalseStruct = { PyVarObject_HEAD_INIT(&PyBool_Type, 0) { 0 } }; struct _longobject _Py_TrueStruct = { PyVarObject_HEAD_INIT(&PyBool_Type, 1) { 1 } };
따라서 Boolean은 python-3.x 의 하위 클래스라고 말할 수 있습니다. int
여기서 True
value 1
를 False
취하고 value를 취합니다 0
. 따라서 매개 변수 로 PyVarObject_HEAD_INIT
with를 type
참조로 PyBool_Type
, ob_size
값 0
으로 1
각각을 호출합니다 .
이제 python-3.x 이후 에는 long
더 이상 존재하지 않습니다. 이들은 병합되었으며 int
객체는 숫자의 크기에 따라 다른 값을 갖습니다.
longlobject
유형 의 소스 코드를 검사하면 다음을 볼 수 있습니다.
/* Long integer representation. The absolute value of a number is equal to SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i) Negative numbers are represented with ob_size < 0; zero is represented by ob_size == 0. In a normalized number, ob_digit[abs(ob_size)-1] (the most significant digit) is never zero. Also, in all cases, for all valid i, 0 <= ob_digit[i] <= MASK. The allocation function takes care of allocating extra memory so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available. CAUTION: Generic code manipulating subtypes of PyVarObject has to aware that ints abuse ob_size's sign bit. */ struct _longobject { PyObject_VAR_HEAD digit ob_digit[1]; };
간단히 말해서,는 _longobject
"숫자"의 배열로 볼 수 있지만 여기에서는 숫자를 십진수가 아니라 따라서 더하거나 곱할 수있는 비트 그룹으로보아야합니다.
이제 주석에 지정된대로 다음과 같이 말합니다.
zero is represented by ob_size == 0.
따라서 값이 0 인 경우 숫자가 추가 되지 않지만 작은 정수 ( CPython에서 2 30 미만의 값 )의 경우 한 숫자가 사용됩니다.
In python-2.x, there were two types of representations for numbers, int
s (with a fixed size), you could see this as "one digit", and long
s, with multiple digits. Since a bool
was a subclass of int
, both True
and False
occupied the same space.
Take a look at the cpython code for True
and False
Internally it is represented as integer
PyTypeObject PyBool_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"bool",
sizeof(struct _longobject),
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
bool_repr, /* tp_repr */
&bool_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
bool_repr, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
bool_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyLong_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
bool_new, /* tp_new */
};
/* The objects representing bool values False and True */
struct _longobject _Py_FalseStruct = {
PyVarObject_HEAD_INIT(&PyBool_Type, 0)
{ 0 }
};
struct _longobject _Py_TrueStruct = {
PyVarObject_HEAD_INIT(&PyBool_Type, 1)
{ 1 }
I haven't seen CPython code for this, but I believe this has something to do with optimization of integers in Python 3. Probably, as long
was dropped, some optimizations were unified. int
in Python 3 is arbitrary-sized int – the same as long
was in Python 2. As bool
stores in the same way as new int
, it affects both.
Interesting part:
>>> (0).__sizeof__()
24
>>> (1).__sizeof__() # Here one more "block" is allocated
28
>>> (2**30-1).__sizeof__() # This is the maximum integer size fitting into 28
28
+ 객체 헤더에 대한 바이트는 방정식을 완료해야합니다.
참고 URL : https://stackoverflow.com/questions/53015922/different-object-size-of-true-and-false-in-python-3
'Programing' 카테고리의 다른 글
ConfigurationManager.AppSettings [Key]는 매번 web.config 파일에서 읽습니까? (0) | 2020.11.12 |
---|---|
JavaScript : 빈 배열, []는 조건부 구조에서 참으로 평가됩니다. (0) | 2020.11.12 |
XML 구문 분석-ElementTree 대 SAX 및 DOM (0) | 2020.11.12 |
'문자열'의 정의 뒤에 숨겨진 역사 (0) | 2020.11.12 |
리플 로우와 리 페인트의 차이점은 무엇입니까? (0) | 2020.11.12 |