python - पायथन 3 में ट्रू और फाल्स के विभिन्न ऑब्जेक्ट आकार




python-3.x python-2.7 (3)

अलग-अलग पायथन वस्तुओं पर जादू के तरीकों (विशेष रूप से __sizeof__ ) के साथ प्रयोग करने से मैं निम्नलिखित व्यवहार पर ठोकर खाई:

पायथन 2.7

>>> False.__sizeof__()
24
>>> True.__sizeof__()
24

अजगर 3.x

>>> False.__sizeof__()
24
>>> True.__sizeof__()
28

पायथन 3 में क्या बदलाव आया जो True के आकार को False आकार से अधिक बनाता है?


ऐसा इसलिए है क्योंकि पाइथन 2 और 3 दोनों में bool int का एक उपवर्ग है।

>>> issubclass(bool, int)
True

लेकिन int बदल गया है।

पायथन 2 में, int एक था जो 32 या 64 बिट्स था, जो सिस्टम पर निर्भर करता था, जैसा कि मनमाना-लंबाई के विपरीत था।

पायथन 3 में, int मनमानी-लंबाई है - Python 2 के long को int में बदल दिया गया और मूल Python 2 को पूरी तरह से गिरा दिया गया।

पायथन 2 में आपको लंबी वस्तुओं 1L और 0 1L लिए समान व्यवहार मिलता है:

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 फैलने पर भी, और अतिरिक्त अंकों की आवश्यकता होती है।

Ie 0 को लंबाई के बाइनरी स्ट्रिंग के रूप में दर्शाया गया है:

<>

और 1 को 30-बिट बाइनरी स्ट्रिंग के रूप में दर्शाया गया है:

<000000000000000000000000000001>

पायथन में डिफ़ॉल्ट कॉन्फ़िगरेशन एक uint32_t में 30 बिट्स का उपयोग करता है; so 2**30 - 1 अभी भी 28 बाइट्स में x86-64 पर फिट बैठता है, और 2**30 को 32 की आवश्यकता होगी;

2**30 - 1 रूप में प्रस्तुत किया जाएगा

<111111111111111111111111111111>

यानी सभी 30 मूल्य बिट्स 1 पर सेट होते हैं; 2 ** 30 को अधिक की आवश्यकता होगी, और इसमें आंतरिक प्रतिनिधित्व होगा

<000000000000000000000000000001000000000000000000000000000000>

24 के बजाय 28 बाइट्स का उपयोग करने वाले True लिए - आपको चिंता करने की आवश्यकता नहीं है। True एक सिंगलटन है और इसलिए किसी भी पायथन प्रोग्राम में कुल 4 बाइट्स ही खोते हैं, True हर उपयोग के लिए 4 नहीं।


मैंने इसके लिए CPython कोड नहीं देखा है, लेकिन मेरा मानना ​​है कि यह Python 3 में पूर्णांक के अनुकूलन के साथ कुछ करना है। संभवतः, जब long गिरा दिया गया था, कुछ अनुकूलन एकीकृत थे। int in Python 3, मनमाने आकार का int है - वही जब long Python 2 में था, long नए int के समान bool स्टोर, दोनों को प्रभावित करता है।

दिलचस्प हिस्सा:

>>> (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

वस्तु हेडर के लिए + बाइट्स समीकरण को पूरा करना चाहिए।


True और False के लिए cpython कोड पर एक नज़र डालें

आंतरिक रूप से इसे पूर्णांक के रूप में दर्शाया जाता है

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 }




python-internals