python - क्यों '() है()' सही है जब '[] है[]' और '{} है{}' वापसी गलत है?



python-3.x tuples (1)

जिन चीज़ों से मुझे पता चला है, [], {} या () का उपयोग वस्तुओं को तत्काल करने के list, dict क्रमशः list, dict या tuple का एक नया उदाहरण देता है; एक नई पहचान के साथ एक नया उदाहरण वस्तु।

जब तक मैंने वास्तव में इसका परीक्षण नहीं किया तब तक यह मेरे लिए स्पष्ट था और मैंने देखा कि () is () वास्तव में अपेक्षित False बजाय True :

>>> () is (), [] is [], {} is {}
(True, False, False)

जैसा कि अपेक्षित है, क्रमशः list() , dict() और tuple() साथ ऑब्जेक्ट्स बनाते समय यह व्यवहार भी प्रकट होता है:

>>> tuple() is tuple(), list() is list(), dict() is dict()
(True, False, False)

tuple() लिए दस्तावेज़ों में जानकारी का एकमात्र प्रासंगिक टुकड़ा मुझे मिल सकता है:

[...] उदाहरण के लिए, tuple('abc') रिटर्न ('a', 'b', 'c') और tuple([1, 2, 3]) रिटर्न (1, 2, 3)यदि कोई तर्क नहीं दिया जाता है, तो कन्स्ट्रक्टर एक नया खाली ट्यूपल बनाता है, ()

कहने का पर्याप्त कारण, यह मेरे प्रश्न का उत्तर देने के लिए पर्याप्त नहीं है।

तो, खाली टुपल्स की एक ही पहचान क्यों होती है जबकि सूचियों या शब्दकोशों जैसे अन्य लोग नहीं करते हैं?


संक्षेप में:

पायथन आंतरिक रूप से ट्यूपल ऑब्जेक्ट्स की C सूची बनाता है जिसका पहला तत्व खाली ट्यूपल होता है। प्रत्येक बार tuple() या () का उपयोग किया जाता है, पायथन उपर्युक्त C सूची में मौजूद मौजूदा वस्तु को वापस कर देगा और एक नया निर्माण नहीं करेगा।

इस तरह की तंत्र dict या list वस्तुओं के लिए मौजूद नहीं है, इसके विपरीत, हर बार खरोंच से पुनर्निर्मित किया जाता है

यह संभवतः इस तथ्य से संबंधित है कि अपरिवर्तनीय वस्तुओं (जैसे टुपल्स) को बदला नहीं जा सकता है, और इस तरह, निष्पादन के दौरान परिवर्तित नहीं होने की गारंटी दी जाती है। frozenset() is frozenset() पर विचार करते समय यह और अधिक ठोस होता frozenset() is frozenset() True ; जैसे () एक खाली frozenset को frozenset के कार्यान्वयन में सिंगलटन माना जाता है । परिवर्तनीय वस्तुओं के साथ, ऐसी गारंटीएं जगह पर नहीं हैं और, इस तरह, उनके शून्य तत्व उदाहरणों को कैश करने के लिए कोई प्रोत्साहन नहीं है (यानी उनकी सामग्री शेष पहचान के साथ बदल सकती है)।

ध्यान दें: यह ऐसा कुछ नहीं है जिस पर निर्भर होना चाहिए, यानी किसी को सिंगल होने के लिए खाली टुपल्स पर विचार नहीं करना चाहिए। दस्तावेज में ऐसी कोई गारंटी स्पष्ट रूप से नहीं बनाई गई है, इसलिए किसी को यह मानना ​​चाहिए कि यह कार्यान्वयन निर्भर है।

कैसे किया जाता है:

सबसे आम मामले में, PyTuple_MAXFREELIST का कार्यान्वयन दो मैक्रोज़ PyTuple_MAXFREELIST और PyTuple_MAXSAVESIZE साथ संकलित किया गया है जो सकारात्मक पूर्णांक पर सेट है। इन मैक्रोज़ के लिए सकारात्मक मान आकार PyTuple_MAXSAVESIZE आकार के साथ PyTuple_MAXSAVESIZE ऑब्जेक्ट्स की एक सरणी के निर्माण में PyTuple_MAXSAVESIZE

जब PyTuple_New को पैरामीटर size == 0 साथ बुलाया जाता है तो यह सूची में नया खाली PyTuple_New जोड़ना सुनिश्चित करता है यदि यह पहले से मौजूद नहीं है:

if (size == 0) {
    free_list[0] = op;
    ++numfree[0];
    Py_INCREF(op);          /* extra INCREF so that this is never freed */
}

फिर, यदि कोई नया खाली टुपल अनुरोध किया गया है, तो इस सूची की पहली स्थिति में स्थित एक नया उदाहरण के बजाय वापस लौटाया जा रहा है:

if (size == 0 && free_list[0]) {
    op = free_list[0];
    Py_INCREF(op);
    /* rest snipped for brevity.. */

ऐसा करने के लिए प्रोत्साहन देने का एक अतिरिक्त कारण यह तथ्य है कि फ़ंक्शन कॉल का इस्तेमाल होने वाले स्थितित्मक तर्कों को पकड़ने के लिए एक टुपल का निर्माण होता है। इसे load_args फ़ंक्शन में ceval.c में देखा जा सकता है:

static PyObject *
load_args(PyObject ***pp_stack, int na)
{
    PyObject *args = PyTuple_New(na);
    /* rest snipped for brevity.. */

जिसे एक ही फाइल में do_call माध्यम से बुलाया जाता है। यदि तर्कों की संख्या शून्य है, तो एक खाली टुपल वापस करने जा रहा है।

संक्षेप में, यह एक ऐसा ऑपरेशन हो सकता है जो अक्सर किया जाता है, इसलिए हर बार एक खाली ट्यूपल का पुनर्निर्माण नहीं करना समझ में आता है।

आगे की पढाई:

अपरिवर्तनीय के साथ सीपीथॉन के कैशिंग व्यवहार पर कुछ और उत्तरों ने प्रकाश डाला:

  • पूर्णांक के लिए, स्रोत में खोदने वाला एक और उत्तर here पाया जा सकता here ।
  • तारों के लिए, here और here , here कुछ जवाब दिए जा सकते here




python-internals