एक और मुद्दा है जो मौजूदा उत्तरों में से किसी में भी इंगित नहीं किया गया है। पायथन को किसी भी दो अपरिवर्तनीय मूल्यों को मर्ज करने की अनुमति है, और पूर्व-निर्मित छोटे अंतर मान केवल ऐसा नहीं हो सकता है। एक पायथन कार्यान्वयन को कभी भी ऐसा करने की गारंटी नहीं दी जाती है, लेकिन वे सभी इसे केवल छोटे ints से अधिक के लिए करते हैं।
एक बात के लिए, कुछ अन्य पूर्व-निर्मित मान हैं, जैसे कि खाली tuple
, str
और bytes
, और कुछ छोटे तार (CPython 3.6 में, यह 256 एकल-वर्ण लैटिन -1 स्ट्रिंग्स है)। उदाहरण के लिए:
>>> a = ()
>>> b = ()
>>> a is b
True
लेकिन साथ ही, गैर-पूर्व-निर्मित मूल्य भी समान हो सकते हैं। इन उदाहरणों पर विचार करें:
>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True
और यह int
मूल्यों तक सीमित नहीं है :
>>> g, h = 42.23e100, 42.23e100
>>> g is h
True
जाहिर है, सीपीथॉन इसके लिए पहले से बनाए गए float
मूल्य के साथ नहीं आता है 42.23e100
। तो, यहाँ क्या हो रहा है?
CPython संकलक की तरह कुछ ज्ञात-अपरिवर्तनीय प्रकार के निरंतर मूल्यों में मर्ज हो जाएगी int
, float
, str
, bytes
, एक ही संकलन इकाई में। एक मॉड्यूल के लिए, पूरा मॉड्यूल एक संकलन इकाई है, लेकिन इंटरैक्टिव दुभाषिया में, प्रत्येक कथन एक अलग संकलन इकाई है। चूंकि c
और d
अलग-अलग बयानों में परिभाषित किए गए हैं, उनके मूल्यों का विलय नहीं किया गया है। चूंकि e
और f
एक ही बयान में परिभाषित किया गया है, उनके मूल्यों को मिला दिया जाता है।
आप देख सकते हैं कि बाइटकोड को डिसाइड करके क्या चल रहा है। एक फ़ंक्शन को परिभाषित करने की कोशिश करें जो उस पर e, f = 128, 128
कॉल करता है और फिर आपको बताता है dis.dis
कि एक निरंतर मूल्य है(128, 128)
>>> def f(): i, j = 258, 258
>>> dis.dis(f)
1 0 LOAD_CONST 2 ((128, 128))
2 UNPACK_SEQUENCE 2
4 STORE_FAST 0 (i)
6 STORE_FAST 1 (j)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480
आप देख सकते हैं कि संकलक ने 128
एक स्थिरांक के रूप में संग्रहीत किया है, भले ही यह वास्तव में बाईटेकोड द्वारा उपयोग नहीं किया गया है, जो आपको यह अनुमान लगाता है कि सीपीथॉन का संकलक कितना कम अनुकूलन करता है। जिसका अर्थ है कि (गैर-खाली) टुपल्स वास्तव में विलीन नहीं होते हैं:
>>> k, l = (1, 2), (1, 2)
>>> k is l
False
रखो कि एक समारोह में, dis
यह, और कम से देखो co_consts
, वहाँ एक है 1
और एक 2
, दो (1, 2)
tuples ही हिस्सा है कि 1
और 2
लेकिन समान नहीं हैं, और एक ((1, 2), (1, 2))
टपल दो अलग-अलग समान tuples है।
एक और अनुकूलन है जो सीपीथॉन करता है: स्ट्रिंग इंटर्निंग। कंपाइलर निरंतर तह के विपरीत, यह स्रोत कोड शाब्दिकों तक सीमित नहीं है:
>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True
दूसरी ओर, यह str
प्रकार तक सीमित है , और आंतरिक भंडारण प्रकार "एससीआई कॉम्पैक्ट", "कॉम्पैक्ट", या "विरासत तैयार" के तार के लिए , और कई मामलों में केवल "एएससीआई कॉम्पैक्ट" को नजरबंद कर दिया जाएगा।
किसी भी दर पर, मान क्या होना चाहिए, के लिए नियम हो सकता है, या कार्यान्वयन से कार्यान्वयन के लिए, और एक ही कार्यान्वयन के संस्करणों के बीच भिन्न नहीं हो सकता है, और शायद एक ही कोड के एक ही कोड के रन के बीच भी हो सकता है ।
यह इसके लिए एक विशिष्ट पायथन के नियमों को सीखने के लायक हो सकता है। लेकिन यह आपके कोड में उन पर भरोसा करने लायक नहीं है। एकमात्र सुरक्षित नियम है:
- ऐसा कोड न लिखें जो दो समान हो, लेकिन अलग-अलग बनाए गए अपरिवर्तनीय मान समान हों (उपयोग न करें
x is y
, उपयोग न करें x == y
)
- ऐसे कोड न लिखें जो दो समान हों, लेकिन अलग-अलग निर्मित अपरिवर्तनीय मान अलग-अलग हों (उपयोग न करें
x is not y
, उपयोग न करें x != y
)
या, दूसरे शब्दों में, केवल is
प्रलेखित एकल (जैसे None
) के लिए परीक्षण करने के लिए उपयोग करते हैं या जो केवल कोड में एक जगह ( _sentinel = object()
मुहावरे की तरह ) बनाए जाते हैं ।