अजगर रेंज में पूर्णांक कैश करता है [-5, 256]
, इसलिए यह उम्मीद की जाती है कि उस सीमा में पूर्णांक भी समान हैं।
आप जो देखते हैं वह समान पाठ के भाग के समान शाब्दिक रूप से अनुकूलन करने वाले पायथन कंपाइलर है।
जब पायथन शेल में टाइप करना प्रत्येक पंक्ति एक पूरी तरह से अलग स्टेटमेंट है, एक अलग पल में पार्स किया जाता है, इस प्रकार:
>>> a = 257
>>> b = 257
>>> a is b
False
लेकिन अगर आप एक ही कोड को फाइल में रखते हैं:
$ echo 'a = 257
> b = 257
> print a is b' > testing.py
$ python testing.py
True
ऐसा तब होता है जब पार्सर के पास यह विश्लेषण करने का मौका होता है कि शाब्दिक उपयोग कहां किया जाता है, उदाहरण के लिए जब इंटरएक्टिव इंटरप्रेटर में किसी फ़ंक्शन को परिभाषित करते हैं:
>>> def test():
... a = 257
... b = 257
... print a is b
...
>>> dis.dis(test)
2 0 LOAD_CONST 1 (257)
3 STORE_FAST 0 (a)
3 6 LOAD_CONST 1 (257)
9 STORE_FAST 1 (b)
4 12 LOAD_FAST 0 (a)
15 LOAD_FAST 1 (b)
18 COMPARE_OP 8 (is)
21 PRINT_ITEM
22 PRINT_NEWLINE
23 LOAD_CONST 0 (None)
26 RETURN_VALUE
>>> test()
True
>>> test.func_code.co_consts
(None, 257)
ध्यान दें कि संकलित कोड में किसके लिए एक एकल स्थिरांक है 257
।
अंत में, पायथन बाइटकोड कंपाइलर बड़े पैमाने पर अनुकूलन (जैसे कि टाइप की गई भाषाएं) करने में सक्षम नहीं है, लेकिन यह आपके विचार से अधिक करता है। इनमें से एक चीज़ शाब्दिक उपयोग का विश्लेषण करना और उन्हें नक़ल करने से बचना है।
ध्यान दें कि इसका कैश से कोई लेना-देना नहीं है, क्योंकि यह फ्लोट के लिए भी काम करता है, जिसमें कैश नहीं है:
>>> a = 5.0
>>> b = 5.0
>>> a is b
False
>>> a = 5.0; b = 5.0
>>> a is b
True
अधिक जटिल शाब्दिकों के लिए, टुपल्स की तरह, यह "काम नहीं करता":
>>> a = (1,2)
>>> b = (1,2)
>>> a is b
False
>>> a = (1,2); b = (1,2)
>>> a is b
False
लेकिन टुपल के अंदर का शाब्दिक हिस्सा है:
>>> a = (257, 258)
>>> b = (257, 258)
>>> a[0] is b[0]
False
>>> a[1] is b[1]
False
>>> a = (257, 258); b = (257, 258)
>>> a[0] is b[0]
True
>>> a[1] is b[1]
True
(ध्यान दें कि निरंतर तह और peephole ऑप्टिमाइज़र बगफिक्स संस्करणों के बीच भी व्यवहार को बदल सकता है, इसलिए जो उदाहरण वापस आते हैं True
या False
मूल रूप से मनमाना है और भविष्य में बदल जाएगा)।
इस बारे में कि आप क्यों देखते हैं कि दो PyInt_Object
बनाए गए हैं, मुझे लगता है कि यह शाब्दिक तुलना से बचने के लिए किया गया है। उदाहरण के लिए, संख्या 257
कई शाब्दिक रूप से व्यक्त की जा सकती है:
>>> 257
257
>>> 0x101
257
>>> 0b100000001
257
>>> 0o401
257
पार्सर के पास दो विकल्प हैं:
- पूर्णांक बनाने से पहले शाब्दिक को कुछ सामान्य आधार में परिवर्तित करें, और देखें कि क्या शाब्दिक समकक्ष हैं। फिर एक पूर्णांक ऑब्जेक्ट बनाएँ।
- पूर्णांक ऑब्जेक्ट बनाएँ और देखें कि क्या वे समान हैं। यदि हाँ, तो केवल एक ही मान रखें और इसे सभी शाब्दिकों को निर्दिष्ट करें, अन्यथा, आपके पास पहले से ही असाइन करने के लिए पूर्णांक हैं।
संभवतः पायथन पार्सर दूसरे दृष्टिकोण का उपयोग करता है, जो रूपांतरण कोड को फिर से लिखने से बचता है और यह भी विस्तार करना आसान है (उदाहरण के लिए यह फ्लोट के साथ भी काम करता है)।
Python/ast.c
फ़ाइल को पढ़ना , वह फ़ंक्शन जो सभी नंबरों को पार्स करता है parsenumber
, जो PyOS_strtoul
पूर्णांक मान प्राप्त करने के लिए कॉल करता है (अंतः के लिए) और अंततः कॉल करता है PyLong_FromString
:
x = (long) PyOS_strtoul((char *)s, (char **)&end, 0);
if (x < 0 && errno == 0) {
return PyLong_FromString((char *)s,
(char **)0,
0);
}
जैसा कि आप यहाँ देख सकते हैं कि पार्सर यह जाँच नहीं करता है कि क्या यह पहले से ही दिए गए मान के साथ पूर्णांक पाया है और इसलिए यह बताता है कि आप क्यों देखते हैं कि दो अंतरंग वस्तुएं बनाई गई हैं, और इसका मतलब यह भी है कि मेरा अनुमान सही था: पार्सर सबसे पहले स्थिरांक बनाता है और उसके बाद ही बाइटकोड को बराबर स्थिरांक के लिए एक ही वस्तु का उपयोग करने के लिए अनुकूलित करता है।
कोड है कि इस जांच करता है में कहीं होना चाहिए Python/compile.c
या Python/peephole.c
, के बाद से इन फ़ाइलों कि बाईटकोड में एएसटी को बदलने हैं।
विशेष रूप से, compiler_add_o
फ़ंक्शन ऐसा लगता है जो इसे करता है। इस टिप्पणी में है compiler_lambda
:
/* Make None the first constant, so the lambda can't have a
docstring. */
if (compiler_add_o(c, c->u->u_consts, Py_None) < 0)
return 0;
तो ऐसा लगता है कि compiler_add_o
फ़ंक्शंस / लैम्ब्डा आदि के लिए स्थिरांक डालने के लिए उपयोग किया जाता है। compiler_add_o
फ़ंक्शन स्थिरांक को एक dict
वस्तु में संग्रहीत करता है , और इस से तुरंत इस बात का अनुसरण करता है कि समान स्थिरांक एक ही स्लॉट में गिर जाएंगे, जिसके परिणामस्वरूप अंतिम बाइटकोड में एक निरंतर होता है।