Programing

Python 3에서 True와 False의 다른 객체 크기

lottogame 2020. 11. 12. 07:42
반응형

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에서 당신의 정확히 같은 동작 얻을 개체 1L0L:

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 - 1x86-64에서 여전히 28 바이트에 맞으며 2**3032가 필요합니다.

2**30 - 1 다음과 같이 표시됩니다.

<111111111111111111111111111111>

즉, 모든 30 값 비트는 1로 설정됩니다. 2 ** 30은 더 많이 필요하며 내부 표현을 갖습니다.

<000000000000000000000000000001000000000000000000000000000000>

24 대신 28 바이트 True사용하는 경우 걱정할 필요가 없습니다. 싱글 톤 이므로 모든 Python 프로그램 에서 4 바이트 만 손실되며 .TrueTrue


둘 다 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은 의 하위 클래스라고 말할 수 있습니다. int여기서 Truevalue 1False취하고 value를 취합니다 0. 따라서 매개 변수 PyVarObject_HEAD_INITwith를 type참조로 PyBool_Type, ob_size0으로 1각각을 호출합니다 .

이제 이후 에는 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 , there were two types of representations for numbers, ints (with a fixed size), you could see this as "one digit", and longs, 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

반응형