2016-11-22 4 views
5

निम्न कोड दिए गए आउटपुट का उत्पादन करता है।__sizeof__ str __sizeof__ से बड़ा है जिसमें एक स्ट्रिंग है जिसमें स्ट्रिंग

import sys 

print('ex1:') 
ex1 = 'Hello' 
print('\t', ex1.__sizeof__()) 

print('\nex2:') 
ex2 = ('Hello', 53) 
print('\t', ex2.__sizeof__()) 

आउटपुट:

ex1: 
    54  
ex2: 
    40 

क्यों करता __sizeof__() प्रिंट एक छोटे परिणाम जब एक दूसरा तत्व माना जाता है? आउटपुट बड़ा नहीं होना चाहिए? मुझे this answer से एहसास है कि मुझे sys.getsizeof() का उपयोग करना चाहिए, लेकिन फिर भी व्यवहार अजीब लगता है। मैं Python 3.5.2 का उपयोग कर रहा हूँ।

इसके अलावा, जैसा @Herbert ने कहा, 'Hello' अप अधिक स्मृति ('Hello',) से लेता है, जो एक tuple है। ऐसा क्यों है?

+0

आपकी पहली वस्तु टुपल नहीं है, यह ब्रांड्स के भीतर एक स्ट्रिंग है। – Kasramvd

उत्तर

13

इस तथ्य यह है कि tuple वस्तुओं (और मैं यकीन है कि स्ट्रिंग से छोड़कर सभी कंटेनरों हूँ) की वजह से है के आकार की गणना के द्वारा अपने-अपने सामग्री की वास्तविक आकार सहित बल्कि करने से उनका आकार नहीं का आकलन पॉइंटर्स PyObject बार वे तत्व होते हैं। यही है, वे पॉइंटर्स को (जेनेरिक) PyObject एस निहित रखते हैं और यही वह है जो इसके समग्र आकार में योगदान देता है।

यह Data Model chapter of the Python Reference के मैनुअल में संकेत दिया गया है:

कुछ वस्तुएं अन्य वस्तुओं को संदर्भ होता है; इन्हें कंटेनर कहा जाता है। कंटेनरों के उदाहरण tuples, सूचियों और शब्दकोश हैं। संदर्भ कंटेनर के मूल्य का हिस्सा हैं।

(। मैं शब्द संदर्भ पर बल कर रहा हूँ)

In PyTupleType, एक struct जहां tuple प्रकार के बारे में जानकारी शामिल है, हम देखते हैं कि tp_itemsize क्षेत्र sizeof(PyObject *) अपने मूल्य के रूप में दिया गया है:

PyTypeObject PyTuple_Type = { 
    PyVarObject_HEAD_INIT(&PyType_Type, 0) 
    "tuple", 
    sizeof(PyTupleObject) - sizeof(PyObject *), 
    sizeof(PyObject *), // <-- sizeof pointer to PyObject's 

32 बिट बनाता है और 64 बिट अजगर के बनाता है एक sizeof(PyObject *) है 8 बाइट के बराबर।

यह वह मान है जो tuple उदाहरण में निहित वस्तुओं की संख्या से गुणा किया जा रहा है। जब हम object_size को देखो, __sizeof__ विधि है कि tuple रों object से विरासत (object.__sizeof__ is tuple.__sizeof__ की जांच), हम यह स्पष्ट रूप से देखें:

static PyObject * 
object_sizeof(PyObject *self, PyObject *args) 
{ 
    Py_ssize_t res, isize; 

    res = 0; 
    isize = self->ob_type->tp_itemsize; 
    if (isize > 0) 
     res = Py_SIZE(self) * isize; // <-- num_elements * tp_itemsize 
    res += self->ob_type->tp_basicsize; 

    return PyLong_FromSsize_t(res); 
} 

देखते हैं कि कैसे isize (tp_itemsize से प्राप्त) Py_SIZE(self) से गुणा किया जाता है, जो, एक और मैक्रो है ob_size मान के अंदर तत्वों की संख्या को इंगित करता है।

यही कारण है कि, यहां तक ​​कि अगर हम एक टपल उदाहरण के अंदर कुछ हद तक एक बड़े स्ट्रिंग बनाने के लिए: इसके अंदर

t = ("Hello" * 2 ** 10,) 

तत्व के साथ के आकार होने:

t[0].__sizeof__()   # 5169 

टपल का आकार उदाहरण:

t.__sizeof__()   # 32 

के बराबर होती है कि बस के अंदर "Hello" साथ में से एक:

t2 = ("Hello",) 
t[0].__sizeof__()   # 54 
t2.__sizeof__()   # 32 Tuple size stays the same. 

तारों के लिए, प्रत्येक व्यक्तिगत चरित्र str.__sizeof__ से लौटाए गए मान को बढ़ाता है। यह, इस तथ्य के साथ कि tuple एस केवल स्टोर पॉइंटर्स, एक भ्रामक इंप्रेशन देता है कि "Hello" में टुपल से बड़ा आकार है।

बस पूर्णता के लिए, unicode__sizeof__ वह है जो इसकी गणना करता है। यह वास्तव में चरित्र आकार के साथ स्ट्रिंग की लंबाई को गुणा करता है (जो इस बात पर निर्भर करता है कि चरित्र 1, 2 और 4 बाइट वर्णों पर निर्भर करता है)।

एकमात्र चीज जो मुझे टुपल्स के साथ नहीं मिल रही है, यही कारण है कि यह मूल आकार (tb_basicsize द्वारा इंगित) को sizeof(PyTupleObject) - sizeof(PyObject *) के रूप में सूचीबद्ध किया गया है। यह कुल आकार से 8 बाइट्स शेड करता है; मुझे इस (अभी तक) के लिए कोई स्पष्टीकरण नहीं मिला है।

+1

एक और शीर्ष जवाब, लेकिन मुझे आश्चर्य है कि इन पायथन-आंतरिक प्रश्नों पर cpython टैग की उपेक्षा की जा रही है –

+0

मैंने सोचा है कि खुद @Chris_Rands। कुछ समय पहले, टैग्स क्यू के माध्यम से स्किम करने के बाद, मुझे एहसास हुआ कि ज्यादातर लोग 'पायथन-इंटर्नल्स' के समान हैं, 'सीपीथॉन' कैसे काम करता है, इसलिए मैं बस उस भावना के साथ रोलिंग कर रहा हूं :-) –

संबंधित मुद्दे

 संबंधित मुद्दे