2008-08-25 14 views
207

क्या इसमें कोई अंतर है:क्या "foo is none" और "foo == कोई नहीं" के बीच कोई अंतर है?

if foo is None: pass 

और

if foo == None: pass 

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

उत्तर

239

is हमेशा True रिटर्न अगर यह __eq__() विधि द्वारा एक ही वस्तु उदाहरण

== जबकि अंत में निर्धारित किया जाता है तुलना

अर्थात


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

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

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

+39

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

+0

तो, आपके मामले में, कोड "एफ == कोई नहीं" क्यों सही है? उलझन में ... – study

47

आप इस object identity and equivalence से पढ़ सकते हैं।

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

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

+0

हमम, मुझे लगता है कि आपका लिंक बदल गया है, जब तक कि आप रुचि नहीं रखते * * पाइथन * – Pat

4

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

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

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

4

@Jason: जब तक foo सही मायने में एक बूलियन मान का प्रतिनिधित्व करता है (:

मैं

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

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

+0

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

+0

गलत। मान लीजिए foo = ""। फिर 'अगर foo' झूठी वापसी करेगा और टिप्पणी' #foo कोई नहीं है 'गलत है। – blokeley

+0

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

23

सावधानी का एक शब्द:

if foo: 
    # do something 

बिल्कुल वैसा ही नहीं है के रूप में:

if x is not None: 
    # do something 

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

12

(ob1 is ob2)(id(ob1) == id(ob2))

+6

... लेकिन (ओबी ओबी 2 है) बहुत तेज़ है। टाइमिट कहता है "(ए बी है)" 0.0365 उपयोगक प्रति लूप है और "(आईडी (ए) == आईडी (बी))" 0.153 उपयोग प्रति लूप है। 4.2x तेज! – AKX

+4

'is' संस्करण को फ़ंक्शन कॉल की आवश्यकता नहीं है, और कोई पाइथन-दुभाषिया विशेषता लुकअप नहीं है; दुभाषिया तुरंत जवाब दे सकता है अगर ob1 वास्तव में, ob2 है। – u0b34a0f6ae

+15

नहीं, ऐसा नहीं है। '{} है {}' गलत है और 'आईडी ({}) == आईडी ({})' हो सकता है (और ** ** सीपीथॉन में ** सच है)। Http://stackoverflow.com/questions/3877230 –

11

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

1

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

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

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

+2

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

1

कुछ और जानकारी:

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

  2. 1 का एक परिणाम के रूप में, is, या नहीं, दो lexically प्रतिनिधित्व किया object रों समान गुण (गुण-ऑफ-द गुण ...) या bool तरह आदिम प्रकार की नहीं

  3. प्रारंभ है सुनिश्चित करता है , 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 है" bar "' का उपयोग न करें। ऐसा करने के लिए एक सिंगल स्वीकार्य कारण नहीं है और जब आप इसकी अपेक्षा नहीं करेंगे तो यह BREAK होगा। तथ्य यह है कि यह अक्सर काम करता है क्योंकि सीपीथन जानता है कि यह दो अपरिवर्तनीय वस्तुओं को बनाने के लिए बेवकूफ होगा, जिनकी एक ही सामग्री है। लेकिन फिर भी यह हो सकता है। – ThiefMaster

+0

@TiefMaster क्या उत्तर में गलत समझने की प्रवृत्ति है? हालांकि, इसे फिर से पढ़ने पर * मैं * इसे "कुछ अपवादों" के उल्लेख के साथ नहीं मिला)। आपका कथन केवल तारों के लिए है और 'int' नहीं, है ना? –

+0

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

8

कोई फर्क नहीं पड़ता क्योंकि वस्तुएं समान रूप से समान होंगी। हालांकि, PEP 8 स्पष्ट रूप से आप is का उपयोग करना चाहिए: कोई नहीं की तरह एकमात्र हमेशा होता है या कभी नहीं समानता ऑपरेटरों, नहीं है के साथ किया जाना चाहिए करने के लिए

तुलना। पहचान के लिए

4

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 
संबंधित मुद्दे