2015-10-27 14 views
11

मैं पूरी तरह से इसस्ट्रिंग चरित्र पहचान विरोधाभास

>>> s = chr(8263) 
>>> x = s[0] 
>>> x is s[0] 
False 

के साथ फंस कर रहा हूँ यह कैसे संभव है? क्या इसका मतलब यह है कि इंडेक्सिंग द्वारा एक स्ट्रिंग कैरेक्टर तक पहुंच एक ही चरित्र का एक नया उदाहरण बनाते हैं? चलो प्रयोग:

>>> L = [s[0] for _ in range(1000)] 
>>> len(set(L)) 
1 
>>> ids = map(id, L) 
>>> len(set(ids)) 
1000 
>>> 

ओह क्या बाइट्स की बर्बादी;) या यह मतलब है कि str.__getitem__ एक छिपा सुविधा है करता है? क्या कोई समझा सकता है?

>>> s = chr(8263) 
>>> t = s 
>>> print(t is s, id(t) == id(s)) 
True True 

यह स्पष्ट है::

लेकिन यह मेरे आश्चर्य का अंत नहीं है ts के लिए एक उपनाम है, तो वे एक ही वस्तु का प्रतिनिधित्व करते हैं और पहचान मेल खाना। लेकिन फिर, कैसे निम्नलिखित संभव है:

>>> print(t[0] is s[0]) 
False 

s और t तो क्या एक ही वस्तु है?

लेकिन बदतर:

>>> print(id(t[0]) == id(s[0])) 
True 

t[0] और s[0] कचरा एकत्र नहीं किया गया है, is ऑपरेटर द्वारा एक ही वस्तु के रूप में माना लेकिन अलग आईडी है कर रहे हैं? क्या कोई समझा सकता है?

+1

आपका चार वास्तव में एक एकल तत्व स्ट्रिंग है, इसलिए हाँ, सूचकांक द्वारा चार तक पहुँचने लंबाई 1. –

+0

मैं इस-'ValueError पाने के नए स्ट्रिंग बनाता है: chr() श्रेणी में नहीं ARG (256)' जब मैं इसे चलाता हूं- 's = chr (8263)' – CrakC

+1

डुप्लिकेट कैसे बताता है 'टी [0] एस है [0] -> गलत' अगर आईडी (टी [0]) == आईडी (एस [0]) -> सही'? –

उत्तर

7

यहां दो अंक हैं।

पहले, अजगर वास्तव में __getitem__ कॉल के साथ एक नई चरित्र पैदा नहीं करता है, लेकिन केवल तभी उस चरित्र क्रमसूचक मूल्य अधिक से अधिक है 256 से

उदाहरण के लिए:

>>> s = chr(256) 
>>> s[0] is s 
True 

>>> t = chr(257) 
>>> t[0] is t 
False 

यह वह जगह है क्योंकि आंतरिक रूप से संकलित getitem फ़ंक्शन एकल chracter के सामान्य मूल्य की जांच करता है और get_latin1_char पर कॉल करता है यदि वह मान 256 या उससे कम है। यह कुछ एकल-वर्ण तारों को साझा करने की अनुमति देता है। अन्यथा, एक नई यूनिकोड ऑब्जेक्ट बनाया गया है।

दूसरा मुद्दा कचरा संग्रह से संबंधित है और दिखाता है कि दुभाषिया स्मृति पते को बहुत जल्दी उपयोग कर सकता है। जब आप लिखते हैं:

>>> s = t # = chr(257) 
>>> t[0] is s[0] 
False 

पायथन पहले दो नए एकल वर्ण तार बनाता है और फिर उनके स्मृति पते की तुलना करता है। इनके पास अलग-अलग पते हैं (हमारे पास उपरोक्त स्पष्टीकरण के अनुसार अलग-अलग वस्तुएं हैं) इसलिए is के साथ ऑब्जेक्ट की तुलना गलत होती है।

दूसरी ओर, हम उचित रूप में विरोधाभासी स्थिति हो सकता है:

>>> id(t[0]) == id(s[0]) 
True 

लेकिन यह तब होता है जब उस में एक बाद में समय पर नई स्ट्रिंग s[0] बनाता है क्योंकि दुभाषिया जल्दी t[0] की स्मृति पते के पुनः उपयोग कर लेता पहर।

आप बाईटकोड इस लाइन का उत्पादन की जांच-पड़ताल (जैसे dis साथ - नीचे देखें), आप देखते हैं कि प्रत्येक पक्ष के पते दिए गए एक के बाद एक आवंटित किए जाते हैं (एक नई स्ट्रिंग वस्तु बनाई गई है और उसके बाद id इस पर कहा जाता है) ।

ऑब्जेक्ट t[0] के संदर्भ में id(t[0]) जितनी जल्दी हो सके शून्य पर ड्रॉप (हम अब पूर्णांक पर तुलना कर रहे हैं, ऑब्जेक्ट पर नहीं)। इसका मतलब यह है कि s[0] उसी मेमोरी एड्रेस का पुन: उपयोग कर सकता है जब इसे बाद में बनाया जाता है।


यहाँ लाइन id(t[0]) == id(s[0]) जो मैं एनोटेट किया है के लिए disassembled बाईटकोड है।

आप देख सकते हैं कि t[0] का जीवनकाल s[0] से पहले समाप्त होता है (इसमें कोई संदर्भ नहीं है) इसलिए इसकी स्मृति का पुन: उपयोग किया जा सकता है।

2   0 LOAD_GLOBAL    0 (id) 
       3 LOAD_GLOBAL    1 (t) 
       6 LOAD_CONST    1 (0) 
       9 BINARY_SUBSCR      # t[0] is created 
      10 CALL_FUNCTION   1  # id(t[0]) is computed... 
                # ...lifetime of string t[0] over 
      13 LOAD_GLOBAL    0 (id) 
      16 LOAD_GLOBAL    2 (s) 
      19 LOAD_CONST    1 (0) 
      22 BINARY_SUBSCR      # s[0] is created... 
                # ...free to reuse t[0] memory 
      23 CALL_FUNCTION   1  # id(s[0]) is computed 
      26 COMPARE_OP    2 (==) # the two ids are compared 
      29 RETURN_VALUE 
+0

आपके लिए जानकारीपूर्ण और दृढ़ प्रतिक्रिया के लिए धन्यवाद। लेकिन यह एक प्रश्न उठाता है: क्या यह तारों की अपरिवर्तनीयता का विरोध नहीं करता है? परिभाषा के अनुसार, एक स्ट्रिंग '' की अपरिवर्तनीयता का अर्थ है कि स्ट्रिंग जीवनकाल के दौरान 's [valid_index]' ऑब्जेक्ट कभी नहीं बदलता है? –

+0

@ पी। ऑर्टिज़: कोई समस्या नहीं, खुशी हुई इससे मदद मिली। अगर मैं आपको सही ढंग से समझता हूं, तो यह स्ट्रिंग ऑब्जेक्ट्स की अपरिवर्तनीयता के विपरीत नहीं है जहां तक ​​मैं देख सकता हूं। पहले भाग के लिए, ऐसा लगता है कि 's]' सिर्फ यह जांचता है कि 's' का i-th वर्ण 0-256 रेंज में है और यदि यह है, तो' chr (i) द्वारा दिए गए सिंगलटन स्ट्रिंग ऑब्जेक्ट को वापस करता है) '। 'आईडी' भाग की तुलना करने के लिए,' t [0] 'का जीवनकाल तब तक खत्म हो गया है जब तक कि पाइथन चिंतित है और इसलिए [0] 'उस मेमोरी पर कब्जा करने के लिए स्वतंत्र है। इसमें कोई स्ट्रिंग ऑब्जेक्ट्स उत्परिवर्तित नहीं हैं। –

+0

मैं स्पष्ट होने की कोशिश करता हूं: पायथन रेफरी। दस्तावेज़ बताते हैं: "जब हम एक कंटेनर की व्यवहार्यता के बारे में बात करते हैं, तो तत्काल निहित वस्तुओं की केवल * पहचान * अंतर्निहित होती है।" तो अब, मान लें कि आपके पास निम्न स्ट्रिंग है: 's = chr (8263)'। यदि आप 's' पर अनुक्रमण करते हैं, उदाहरण के लिए' x = s [0] 'के रूप में एक निर्दोष असाइनमेंट, *' 'में पहले आइटम के * पहचान * * बदल गया है * (str.getitem' एक नया मान देता है जैसा कि आपकी प्रतिक्रिया में बताया गया है)। मेरा मतलब यह है कि 'str .__ getitem__' एक उत्परिवर्तनीय विधि है (स्ट्रिंग स्थिति बदल दी गई है)। लेकिन, एक अपरिवर्तनीय वस्तु में कोई उत्परिवर्तन विधियां नहीं होती हैं। –

0

is पहचान की तुलना करें और == मूल्यों की तुलना करें। यह जांचें doc

Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The ‘is‘ operator compares the identity of two objects; the id() function returns an integer representing its identity (currently implemented as its address). An object’s type is also unchangeable.

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