"फू कोई नहीं है" और "फू == कोई नहीं" के बीच कोई अंतर है?


217

क्या इसमें कोई अंतर है:

if foo is None: pass

तथा

if foo == None: pass

अधिकांश पायथन कोड (और कोड मैं खुद लिखता हूं) में देखा गया यह सम्मेलन पूर्व है, लेकिन मैं हाल ही में कोड का उपयोग किया था जो बाद का उपयोग करता है। कोई भी नहीं (और केवल उदाहरण, IIRC) कोई भी नहीं है, इसलिए यह सही नहीं है? क्या ऐसी कोई परिस्थितियां हैं जिनमें यह हो सकता है?

जवाबों:


253

isTrueयदि वह उसी वस्तु उदाहरण की तुलना करता है, तो हमेशा लौटता है

जबकि ==अंततः __eq__()विधि द्वारा निर्धारित किया जाता है

अर्थात


>>> class Foo(object):
       def __eq__(self, other):
           return True

>>> f = Foo()
>>> f == None
True
>>> f is None
False

51
आप यह जोड़ना चाहते हैं कि कोई भी एकल नहीं है, इसलिए "कोई नहीं कोई भी नहीं" हमेशा सत्य होता है।
ई-सिटिस

43
और आप जोड़ना चाह सकते हैं कि isऑपरेटर को अनुकूलित नहीं किया जा सकता है (उपयोगकर्ता द्वारा परिभाषित वर्ग द्वारा अतिभारित)।
मार्टीन्यू

@study विधि __eq__(self)एक विशेष अंतर्निहित विधि है जो यह निर्धारित करती है कि ==पायथन ऑब्जेक्ट पर उपयोग किए जाने पर कैसे संभाला जाता है। यहां हमने इसे ओवरराइड कर दिया है ताकि जब यह ==प्रकार की वस्तुओं पर उपयोग किया जाए तो Fooयह हमेशा सही हो। isऑपरेटर के लिए एक समतुल्य विधि नहीं है और इसलिए व्यवहार isको उसी तरह नहीं बदला जा सकता है।
ब्रेंडन

क्या यह इसलिए है क्योंकि फू क्लास की परिभाषा में कंस्ट्रक्टर नहीं है, यानी, इनिट फ़ंक्शन?
अध्ययन करें

49

आप इस ऑब्जेक्ट पहचान और तुल्यता को पढ़ना चाह सकते हैं ।

कथन 'is' का उपयोग ऑब्जेक्ट आइडेंटिटी के लिए किया जाता है, यह जाँचता है कि क्या ऑब्जेक्ट एक ही उदाहरण (मेमोरी में समान एड्रेस) को संदर्भित करते हैं।

और '==' कथन समानता (समान मूल्य) को संदर्भित करता है।


हम्म, मुझे लगता है कि आपका लिंक बदल गया है, जब तक आप अजगर से बाहरी कार्यों को कॉल करने
पैट

मैंने बस कोशिश की a=1;b=1;print(a is b) # True। कोई भी विचार क्यों a is bसच हो जाता है भले ही वे 2 अलग-अलग वस्तु (स्मृति में अलग-अलग पता) लगते हों?
जॉनी चिउ

24

चेतावनी:

if foo:
  # do something

है बिल्कुल के रूप में एक ही:

if x is not None:
  # do something

पूर्व एक बूलियन मूल्य परीक्षण है और विभिन्न संदर्भों में असत्य का मूल्यांकन कर सकता है। कई चीजें हैं जो बूलियन मूल्य परीक्षणों में झूठ का प्रतिनिधित्व करती हैं उदाहरण के लिए खाली कंटेनर, बूलियन मान। कोई भी इस स्थिति में असत्य का मूल्यांकन नहीं करता है लेकिन अन्य चीजें भी करते हैं।


12

(ob1 is ob2) के बराबर (id(ob1) == id(ob2))


6
... लेकिन (ob2 ob2 है) एक बहुत तेजी से है। टाइमिट कहता है "(a है b)" प्रति पाश 0.0365 usec है और "(id (a) == id (b))" प्रति पाश 0.153 usec है। 4.2x तेज!
AKX

4
isसंस्करण में कोई भी समारोह कॉल, और सभी में कोई अजगर-दुभाषिया विशेषता देखने की जरूरत है; दुभाषिया तुरंत जवाब दे सकता है अगर ob1 है, वास्तव में, ob2।
u0b34a0f6ae

17
नहीं, यह नहीं है। {} is {}गलत है और id({}) == id({})हो सकता है (और है CPython में) सच। देखें stackoverflow.com/questions/3877230
पिओर Dobrogost

12

कारण foo is Noneयह है कि पसंदीदा तरीका यह है कि आप एक ऐसी वस्तु को संभाल रहे हैं जो स्वयं को परिभाषित करती है __eq__, और यह उस वस्तु को परिभाषित करती है जो किसी के बराबर नहीं है। इसलिए, हमेशा उपयोग करें foo is Noneयदि आपको यह देखने की आवश्यकता है कि क्या यह संक्रमित है None


8

इसमें कोई अंतर नहीं है क्योंकि जो वस्तुएं समान हैं वे निश्चित रूप से समान होंगी। हालाँकि, पीईपी 8 स्पष्ट रूप से बताता है कि आपको इसका उपयोग करना चाहिए is:

सिंगलेट्स की तुलना किसी के साथ हमेशा नहीं की जानी चाहिए, या नहीं, कभी भी समानता ऑपरेटर नहीं हैं।


7

isपहचान के लिए परीक्षण, समानता नहीं । आपके कथन के लिए foo is none, पायथन बस वस्तुओं के मेमोरी एड्रेस की तुलना करता है। इसका मतलब है कि आप सवाल पूछ रहे हैं "क्या मेरे पास एक ही वस्तु के लिए दो नाम हैं?"

==दूसरी ओर __eq__()विधि द्वारा निर्धारित समानता के लिए परीक्षण । यह पहचान की परवाह नहीं करता है।

In [102]: x, y, z = 2, 2, 2.0

In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)

In [104]: x is y
Out[104]: True

In [105]: x == y
Out[105]: True

In [106]: x is z
Out[106]: False

In [107]: x == z
Out[107]: True

Noneएक सिंगलटन ऑपरेटर है। तो None is Noneहमेशा सच है।

In [101]: None is None
Out[101]: True

5

किसी के लिए भी समानता (==) और पहचान (()) के बीच अंतर नहीं होना चाहिए। NoType शायद समानता के लिए पहचान लौटाता है। चूँकि कोई भी एकमात्र उदाहरण नहीं है जो आप NoType का बना सकते हैं (मुझे लगता है कि यह सच है), दोनों ऑपरेशन समान हैं। अन्य प्रकारों के मामले में हमेशा ऐसा नहीं होता है। उदाहरण के लिए:

list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"

यह "समान" प्रिंट करेगा क्योंकि सूचियों में एक तुलना ऑपरेशन है जो पहचान की डिफ़ॉल्ट वापसी नहीं है।


5

@ जेसन :

मैं की तर्ज पर कुछ और उपयोग करने की सलाह देता हूं

if foo:
    #foo isn't None
else:
    #foo is None

मुझे "अगर फू:" का उपयोग करना पसंद नहीं है, जब तक कि फू वास्तव में एक बूलियन मान (यानी 0 या 1) का प्रतिनिधित्व नहीं करता है। यदि foo एक स्ट्रिंग या एक वस्तु या कुछ और है, "if foo:" काम कर सकता है, लेकिन यह मेरे लिए एक आलसी शॉर्टकट की तरह दिखता है। यदि आप यह देखने के लिए जाँच कर रहे हैं कि क्या x कोई नहीं है, तो "x कोई नहीं:" कहें।


"अगर" के साथ खाली तार / सूचियों के लिए जाँच पसंदीदा तरीका है। बूलियन रूपांतरण अच्छी तरह से परिभाषित है, और यह कम कोड है जो बेहतर प्रदर्शन भी करता है। उदाहरण के लिए "if len (mylist) == 0" करने का कोई कारण नहीं।
truppo

गलत। मान लीजिए फू = ""। फिर if fooझूठे लौटेंगे और टिप्पणी #foo is Noneगलत है।
ब्‍लेक्‍ले

डाउनवोटर्स पर ध्यान दें - मेरा उत्तर एक उत्तर को उद्धृत कर रहा है जो तब से हटा दिया गया है और इससे असहमत है। यदि आपको मेरे उत्तर में कोड पसंद नहीं है , तो आपको अपवोट करने की आवश्यकता है । :-)
ग्रीम पेरो

2

कुछ और विवरण:

  1. isखंड वास्तव में चेकों दो अगर objectरों एक ही स्मृति स्थान या बिल्कुल भी नहीं कर रहे हैं। यानी वे दोनों एक ही मेमोरी लोकेशन की ओर इशारा करते हैं और एक ही हैं id

  2. 1 के परिणाम के रूप में, isयह सुनिश्चित करता है कि या नहीं, दो शाब्दिक प्रतिनिधित्व वाले objectसमरूप गुण हैं (विशेषताएँ-की-विशेषताएँ)) या नहीं

  3. जैसे आदिम प्रकार के आरंभ होने bool, int, string(कुछ अपवाद के साथ), NoneTypeएक ही मूल्य होने हमेशा एक ही स्मृति स्थान में हो जाएगा।

उदाहरण के लिए

>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True

और चूंकि NoneTypeकेवल अजगर की "लुक-अप" तालिका में स्वयं का एक उदाहरण हो सकता है इसलिए पूर्व और उत्तरार्द्ध डेवलपर की एक प्रोग्रामिंग शैली के अधिक हैं, जिन्होंने कोड लिखा था (शायद स्थिरता के लिए) लेकिन फिर कोई सूक्ष्म तार्किक कारण रहा। एक दूसरे को चुनें।


2
हर कोई इसे पढ़ रहा है: some_string is "bar"तार कभी भी तुलना करने के लिए उपयोग न करें । ऐसा करने के लिए कोई एकल स्वीकार्य रिपोर्ट नहीं है और जब आप इसकी उम्मीद नहीं करेंगे तो यह पूरी हो जाएगी। तथ्य यह है कि यह अक्सर काम करता है क्योंकि CPython जानता है कि यह दो अपरिवर्तनीय वस्तुओं को बनाने के लिए बेवकूफ़ होगा जो समान सामग्री है। लेकिन यह फिर भी हो सकता है।
थोमास्टर

@ThiefMaster के जवाब में गलत धारणा की प्रवृत्ति है? हालाँकि, इसे दोबारा पढ़ने पर मैं इसे (कुछ अपवादों के उल्लेख के साथ) नहीं पा सका। आपका बयान केवल तार के लिए है और intसही नहीं है ?
ब्लीडिंग फिंगर्स

वास्तव में नहीं, लेकिन जब से आपके पास आपके उत्तर में यह उदाहरण है मैंने सोचा कि यह उपयोगकर्ताओं को चेतावनी देने के लिए एक अच्छा विचार होगा कि यह वास्तव में एक बुरा विचार है। शायद उस लाइन के पीछे "# cpython specific / not गारंटीड" जैसा कुछ जोड़ दें ...
ThiefMaster

1

जॉन माचिन का निष्कर्ष जो Noneएक सिंगलटन है वह इस कोड के अनुसार निष्कर्ष निकाला गया है।

>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>> 

चूंकि Noneएक सिंगलटन है, x == Noneऔर x is Noneउसी का परिणाम होगा। हालांकि, मेरे सौंदर्यवादी मत में, x == Noneसबसे अच्छा है।


2
मैं इस जवाब के अंत में राय से असहमत हूं। जब स्पष्ट रूप से किसी के साथ तुलना नहीं की जाती है, तो आमतौर पर यह उद्देश्य होता है कि प्रश्न में Noneवस्तु बिल्कुल वस्तु है। तुलनात्मक रूप से, एक व्यक्ति शायद ही कभी किसी अन्य संदर्भ में किसी अन्य उपयोग किए गए को देखता हो, सिवाय इसके कि Falseअन्य मूल्यों के समान हो । उन मामलों में ऐसा करना अधिक मुहावरेदार हैif x: pass
सिंगलनेग्मेंटेशन इलिमिनेशन

0
a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence 


a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.