पायथन का "समझना" ऑपरेटर है


109

isऑपरेटर चरों के मान, लेकिन उदाहरणों खुद को मेल नहीं खाता।

इसका वास्तव में क्या अर्थ है?

मैंने दो वैरिएबल्स को नाम दिया xऔर yदोनों वैरिएबल्स में समान वैल्यू असाइन करने की घोषणा की , लेकिन जब मैं isऑपरेटर का उपयोग करता हूं तो यह गलत हो जाता है ।

मुझे एक स्पष्टीकरण की आवश्यकता है। यहाँ मेरा कोड है।

x = [1, 2, 3]
y = [1, 2, 3]

print(x is y)  # It prints false!

संबंधित प्रश्न stackoverflow.com/questions/38189660/…
कासरवंद

जवाबों:


181

आप गलत समझते हैं कि isऑपरेटर क्या परीक्षण करता है। यह परीक्षण करता है कि क्या दो चर एक ही वस्तु को इंगित करते हैं , न कि यदि दो चर का एक ही मूल्य हो।

isऑपरेटर के लिए प्रलेखन से :

ऑब्जेक्ट पहचान के लिए ऑपरेटर isऔर is notपरीक्षण: x is yसच है अगर और केवल अगर xऔर yएक ही वस्तु हैं।

==इसके बजाय ऑपरेटर का उपयोग करें :

print(x == y)

यह प्रिंट करता है Truexऔर yदो अलग-अलग सूचियाँ हैं:

x[0] = 4
print(y)  # prints [1, 2, 3]
print(x == y)   # prints False

यदि आप उस id()फ़ंक्शन का उपयोग करते हैं जिसे आप देखेंगे xऔर yउसके अलग-अलग पहचानकर्ता होंगे:

>>> id(x)
4401064560
>>> id(y)
4401098192

लेकिन अगर आप दोनों को एक ही वस्तु के लिए निर्दिष्ट yकरने के लिए थे x:

>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True

और isदिखाता है कि दोनों एक ही वस्तु हैं, यह लौटाता है True

याद रखें कि पायथन में, नाम केवल लेबल हैं संदर्भ मान ; आपके पास एक ही ऑब्जेक्ट पर कई नाम इंगित कर सकते हैं। isआपको बताता है कि क्या दो नाम एक ही वस्तु की ओर इशारा करते हैं। ==आपको बताता है कि क्या दो नाम उन वस्तुओं को संदर्भित करते हैं जिनके समान मूल्य हैं।


13
तो, A is Bजैसा है वैसा ही है id(A) == id(B)
imallett

2
@imallett: यह एक ही परीक्षण के लिए एक प्रॉक्सी है, बशर्ते आप id(A)एक चर में संग्रहित न करें और बाद variable == id(B)में भी काम करने की उम्मीद करें; यदि Aइस बीच हटा Bदिया गया था, तो एक ही मेमोरी स्थान दिया जा सकता था।
मार्टिजन पीटरर्स

1
टिप्पणियों में प्रारूपित नहीं किया जा सका। लेकिन एक दिलचस्प बात है। :) >>> x = 5 \n>>> y = 5 \n>>> x is y \nTrue \n>>> x == y \nTrue \n>>>\n
हरनध

5
छोटे पूर्णांकों को CPython में इंटर्न किया जाता है क्योंकि वे इतनी बार उपयोग किए जाते हैं। यह एक अनुकूलन है। x = 5; y = 5; x y => सही है क्योंकि id (x) == id (y)। यह वही पूर्णांक वस्तु है जिसका पुन: उपयोग किया जाता है। अजगर में काम करता है क्योंकि पूर्णांक अपरिवर्तनीय हैं। यदि आप x = 1.0 करते हैं; y = 1.0 या x = 9999; y = 9999, यह एक ही पहचान नहीं होगी, क्योंकि फ्लोट्स और बड़े इन्ट्स इंटर्न नहीं हैं।
मैग्नस लाइकेज

1
@ MagnusLyckå अन्य आशावादी हैं जो अपरिवर्तनीय वस्तुओं को कैश कर सकते हैं। उदाहरण के लिए, यदि आप एक नए फ़ंक्शन में या इंटरएक्टिव इंटरप्रेटर में एक अलग अर्धविराम के साथ अपना उदाहरण चलाते हैं, तो आप पाएंगे कि उनके पास भी यही आईडी है।
मार्टिन पीटर्स

60

एक और डुप्लिकेट पूछ रहा था कि दो समान तार आम तौर पर समान क्यों नहीं हैं, जो वास्तव में यहां उत्तर नहीं दिया गया है:

>>> x = 'a' 
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False

तो, वे एक ही स्ट्रिंग क्यों नहीं हैं? विशेष रूप से यह दिया:

>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True

चलो दूसरे भाग को थोड़ा सा हटा दें। पहला सच कैसे हो सकता है?

दुभाषिया के पास एक "इंटर्निंग टेबल" होना चाहिए, स्ट्रिंग ऑब्जेक्ट्स के लिए एक टेबल मैपिंग स्ट्रिंग मान, इसलिए हर बार जब आप सामग्री के साथ एक नया स्ट्रिंग बनाने की कोशिश करते हैं 'abc', तो आपको उसी ऑब्जेक्ट को वापस मिलता है। इंटर्नशिप कैसे काम करती है, इस पर विकिपीडिया में अधिक विस्तृत चर्चा है।

और पायथन में एक स्ट्रिंग इंटर्निंग टेबल है; आप sys.internविधि के साथ मैन्युअल रूप से स्ट्रिंग्स को इंटर्न कर सकते हैं ।

वास्तव में, पायथन को किसी भी अपरिवर्तनीय प्रकार को स्वचालित रूप से इंटर्न करने की अनुमति है, लेकिन ऐसा करने की आवश्यकता नहीं है। अलग-अलग कार्यान्वयन अलग-अलग मूल्यों को आंतरिक करेंगे।

CPython (आप जिस कार्यान्वयन का उपयोग कर रहे हैं यदि आप नहीं जानते हैं कि आप किस कार्यान्वयन का उपयोग कर रहे हैं) तो ऑटो-इंटर्न्स छोटे पूर्णांक और कुछ विशेष एकल जैसे False, लेकिन तार नहीं (या बड़े पूर्णांक, या छोटे ट्यूपल, या कुछ और)। आप इसे बहुत आसानी से देख सकते हैं:

>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False

ठीक है, लेकिन समान zऔर wसमान क्यों थे ?

यह दुभाषिया स्वचालित रूप से इंटर्निंग नहीं है, यह संकलक तह मान है।

एक ही संकलन समय स्ट्रिंग एक ही मॉड्यूल में दो बार प्रकट होता है (वास्तव में क्या यह मतलब है परिभाषित-यह करने के लिए, एक स्ट्रिंग शाब्दिक रूप में एक ही बात नहीं है क्योंकि कठिन है r'abc', 'abc'और 'a' 'b' 'c'सभी विभिन्न शाब्दिक लेकिन एक ही कर रहे हैं स्ट्रिंग-लेकिन आसान समझने के लिए सहज ज्ञान युक्त), संकलक केवल दो संदर्भों के साथ, स्ट्रिंग का एक उदाहरण बनाएगा।

वास्तव में, कंपाइलर आगे भी 'ab' + 'c'जा सकता है : 'abc'ऑप्टिमाइज़र द्वारा परिवर्तित किया जा सकता है , जिस स्थिति में इसे एक 'abc'ही मॉड्यूल में एक स्थिर के साथ एक साथ मोड़ा जा सकता है ।

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


तो, एक प्रोग्रामर के रूप में आपको इसके बारे में क्या करना चाहिए?

कुछ नहीं। यदि आपके पास दो अपरिवर्तनीय मूल्य समान हैं, तो आपके पास देखभाल करने का कोई कारण नहीं है। यदि आप जानना चाहते हैं कि आप a is bइसके स्थान पर कब उपयोग कर सकते हैं a == b, तो आप गलत प्रश्न पूछ रहे हैं। बस हमेशा a == bदो मामलों को छोड़कर उपयोग करें :

  • अधिक पठनीय तुलना के लिए सिंगलटन मान जैसे x is None
  • परिवर्तनशील मूल्यों के लिए, जब आपको यह जानना xहोगा कि क्या उत्परिवर्तन प्रभावित करेगा y

1
उत्कृष्ट स्पष्टीकरण, विशेष रूप से अंत में आपकी सलाह।
डेविड

उस विस्तृत विवरण के लिए धन्यवाद। क्या किसी को पता है: यदि संकलक तह मूल्यों के कारण समान हैं wऔर संदर्भों की जांच करने के लिए zभी, यह REPL में काम क्यों करता है id()? Python 3.7
ची-ची

8

isयदि वे वास्तव में एक ही वस्तु हैं तो केवल सही रिटर्न। यदि वे समान होते, तो एक में बदलाव दूसरे में भी दिखाई देता। यहाँ अंतर का एक उदाहरण है।

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]

8

डुप्लिकेट प्रश्न से प्रेरित , यह सादृश्य काम कर सकता है:

# - Darling, I want some pudding!
# - There is some in the fridge.

pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True

# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.

pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False

3
सिर्फ व्यक्तिगत स्वाद हो सकता है (कोई सज़ा का इरादा नहीं) लेकिन मुझे यह सादृश्य मददगार से ज्यादा भ्रमित करने वाला लगा और जब मुझे मेरे फ्रिज में कोई नहीं है तो मुझे हलवा खाने की इच्छा हुई :( मुझे लगता है कि मार्क रैंसम का जवाब है, हालांकि अधिक उबाऊ है, शायद अधिक शिक्षाप्रद
टॉम

1
@TomClose: इस सवाल पर कई ठीक जवाब हैं, पर्याप्त है ताकि उत्तोलन के लिए जगह हो। साथ ही, मुझे हलवा भी चाहिए।
आमदन

5

isऔर is notपायथन में दो पहचानकर्ता हैं। isऑपरेटर चर के मूल्यों की तुलना नहीं करता है, लेकिन चर की पहचान की तुलना करता है। इस पर विचार करो:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>

उपरोक्त उदाहरण आपको दिखाता है कि पहचान (Cpython में मेमोरी एड्रेस भी हो सकती है) दोनों के लिए अलग है aऔर b(भले ही उनके मूल्य समान हों)। इसीलिए जब आप कहते हैं कि a is bयह दोनों ऑपरेंड की पहचान में बेमेल के कारण गलत है। हालाँकि जब आप कहते हैं a == b, यह सही है क्योंकि ==ऑपरेशन केवल यह सत्यापित करता है कि दोनों ऑपरेंड के पास एक ही मान है जो उन्हें सौंपा गया है।

दिलचस्प उदाहरण (अतिरिक्त ग्रेड के लिए):

>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>

उपरोक्त उदाहरण में, भले ही aऔर bदो अलग-अलग चर हैं, a is bवापस आ गए True। इसका कारण यह है के प्रकार है aहै intजो अपरिवर्तनीय वस्तु है। तो अजगर (मुझे लगता है कि स्मृति को बचाने के लिए) उसी वस्तु को आवंटित किया bगया था जब इसे उसी मूल्य के साथ बनाया गया था। तो इस मामले में, चर की पहचान मिलान और a is bनिकली True

यह सभी अपरिवर्तनीय वस्तुओं के लिए लागू होगा:

>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>

उम्मीद है की वो मदद करदे।


यह वास्तविक अच्छा उदाहरण है। विस्तृत जानकारी के लिए धन्यवाद।
हरानध

लेकिन एक = 123456789 b = 123456789
user2183078

अजगर -5से कम या अधिक सब कुछ 256गलत होगा। पायथन कैश रेंज में संख्या -5, 256]।
स्मार्ट

जैसा कि आप दिखाते हैं कि सभी अपरिवर्तनीय वस्तुओं को साझा नहीं किया जाएगा, जो कि कुछ वस्तुओं के लिए पायथन रनटाइम द्वारा लागू किया गया अनुकूलन है, लेकिन अन्य नहीं। छोटे पूर्णांक साझा करने की प्रक्रिया अच्छी तरह से प्रलेखित है, लेकिन मुझे नहीं लगता कि यह स्ट्रिंग इंटर्निंग के लिए है
मार्क रैनसम

4

x is yid(x) == id(y)वस्तुओं की पहचान की तुलना के समान है ।

जैसा कि @ tomasz-kurgan ने टिप्पणी में बताया कि isऑपरेटर कुछ वस्तुओं के साथ असामान्य व्यवहार करता है।

उदाहरण के लिए

>>> class A(object):
...   def foo(self):
...     pass
... 
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True

संदर्भ;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24


नहीं, यह नहीं है। यह ज्यादातर मामलों में समान व्यवहार कर सकता है, लेकिन यह हमेशा सच नहीं होता है। देखें इस - पृष्ठ के बिल्कुल नीचे, बुलेट 6 .:> (...), तो आप कुछ उपयोग में उचित रूप में असामान्य व्यवहार देख सकते हैं की है ऑपरेटर, उदाहरण के तरीकों, या स्थिर और कम से कम काम कर रहे उदाहरण के बीच उन को शामिल तुलना की तरह : `वर्ग ए (ऑब्जेक्ट): डीईएफ फू (स्वयं): पास ए = ए () प्रिंट a.foo एक a.foo प्रिंट आईडी (a.foo) == आईडी (a.foo)`
टॉमस

3

जैसा कि आप यहां एक छोटे पूर्णांक में देख सकते हैं। 257 से ऊपर की संख्या एक छोटी स्याही नहीं है, इसलिए इसकी गणना एक अलग वस्तु के रूप में की जाती है।

==इस मामले में इसके बजाय उपयोग करना बेहतर है ।

अधिक जानकारी यहाँ है: http://docs.python.org/2/c-api/int.html


2

एक्स एक सरणी को इंगित करता है, वाई एक अलग सरणी को इंगित करता है। वे सरणियाँ समान हैं, लेकिन isऑपरेटर उन बिंदुओं को देखेगा, जो समान नहीं हैं।


5
अजगर में संकेत नहीं होते हैं। आपको अपनी शब्दावली को कसने की आवश्यकता है।
डेविड हेफर्नन

3
यह आंतरिक रूप से जावा और अन्य कई भाषाओं की तरह ही होता है। वास्तव में, isऑपरेटर की कार्यक्षमता यह दर्शाती है।
नेको

5
कार्यान्वयन विवरण क्या मायने नहीं रखते हैं। प्रलेखन शब्दावली "वस्तु पहचान" का उपयोग करता है। तो आपको करना चाहिए। "ऑपरेटर है और वस्तु पहचान के लिए परीक्षण नहीं है: x y सत्य है अगर और केवल यदि x और y समान वस्तु हैं। x y y व्युत्क्रम सत्य मान नहीं है।"
डेविड हेफर्नन

1
@ नेको: सीपीथॉन आंतरिक रूप से पॉइंटर्स का उपयोग करता है। लेकिन जाहिर है कि Jython (Java में लागू) और PyPy (पायथन के सबसेट में लागू) पॉइंटर्स का उपयोग नहीं करते हैं। PyPy में, कुछ वस्तुओं के पास idतब तक नहीं होगा जब तक आप इसके लिए नहीं पूछेंगे।
अवतरण

1

यह ऑब्जेक्ट आइडेंटिटी की तुलना करता है, अर्थात, चर स्मृति में एक ही ऑब्जेक्ट को संदर्भित करता है या नहीं। यह ==जावा या सी की तरह है (जब पॉइंटर्स की तुलना करते हैं)।


1

फलों के साथ एक सरल उदाहरण

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )

आउटपुट:

True
False
False

अगर तुम कोशिश करो

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )

आउटपुट अलग है:

True
True
True

ऐसा इसलिए है क्योंकि == ऑपरेटर चर की सामग्री की तुलना करता है। 2 चर की पहचान की तुलना करने के लिए उपयोग है ऑपरेटर है

पहचान संख्या प्रिंट करने के लिए:

print ( id( variable ) )

-3

isऑपरेटर और कुछ नहीं बल्कि एक अंग्रेजी संस्करण है ==। क्योंकि दोनों सूचियों की आईडी अलग-अलग हैं इसलिए उत्तर गलत है। तुम कोशिश कर सकते हो:

a=[1,2,3]
b=a
print(b is a )#True

* क्योंकि दोनों सूची की आईडी एक ही होगी


is'का अंग्रेजी संस्करण नहीं है =='
डेविड बक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.