इस सवाल पर एक टिप्पणी में , मैंने एक बयान देखा जिसका उपयोग करने की सिफारिश की गई थी
result is not None
बनाम
result != None
मैं सोच रहा था कि अंतर क्या है, और एक दूसरे पर सिफारिश क्यों की जा सकती है?
इस सवाल पर एक टिप्पणी में , मैंने एक बयान देखा जिसका उपयोग करने की सिफारिश की गई थी
result is not None
बनाम
result != None
मैं सोच रहा था कि अंतर क्या है, और एक दूसरे पर सिफारिश क्यों की जा सकती है?
जवाबों:
==
एक समानता परीक्षण है । यह जाँचता है कि क्या दाहिने हाथ की ओर और बाएं हाथ की तरफ समान वस्तुएं हैं (उनके __eq__
या __cmp__
तरीकों के अनुसार )।
is
एक पहचान परीक्षा है । यह जाँच करता है कि क्या दाहिने हाथ की तरफ और बाएं हाथ की तरफ एक ही वस्तु है। कोई कार्यप्रणाली नहीं की जाती है, ऑब्जेक्ट is
ऑपरेशन को प्रभावित नहीं कर सकते हैं ।
आप सिंगलटन के लिए is
(और is not
) का उपयोग करते हैं , जैसे None
, जहाँ आप उन वस्तुओं के बारे में परवाह नहीं करते हैं जो होने का नाटक करना चाहते हैं None
या जहाँ आप उन वस्तुओं की रक्षा करना चाहते हैं जिनके खिलाफ तुलना की जा रही है None
।
None
कुछ तरीके हैं और लगभग कोई विशेषता नहीं है। यदि आपके __eq__
परीक्षण से विधि या विशेषता की उम्मीद है, तो यह टूट सकता है। def __eq__( self, other ): return self.size == other.size
। उदाहरण के लिए, अगर other
ऐसा होता है तो टूट जाएगा None
।
is
जावा की तरह है ==
। अजगर का ==
जावा की तरह है .equals()
। बेशक यह केवल तभी मदद करता है जब आप जावा को जानते हैं।
is
तरह है ===
(बहुत बराबर), और इसके विपरीत is not
की तरह है !==
(वास्तव में बराबर नहीं)।
is not
एक भी ऑपरेटर या यह सिर्फ का परिणाम negating है is
की तरह आंतरिक रूप से not foo is bar
?
पहले, मुझे कुछ शर्तों पर जाने दें। यदि आप केवल अपने प्रश्न का उत्तर चाहते हैं, तो "अपने प्रश्न का उत्तर दें" पर स्क्रॉल करें।
वस्तु पहचान : जब आप एक वस्तु बनाते हैं, तो आप इसे एक चर में निर्दिष्ट कर सकते हैं। फिर आप इसे दूसरे चर पर भी असाइन कर सकते हैं। और दुसरी।
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
इस मामले में cancel
, close
और, dismiss
सभी एक ही ऑब्जेक्ट को मेमोरी में संदर्भित करते हैं। आपने केवल एक Button
ऑब्जेक्ट बनाया है , और सभी तीन चर इस एक ऑब्जेक्ट को संदर्भित करते हैं। हम कहते हैं कि cancel
, close
और dismiss
सभी समान वस्तुओं को संदर्भित करते हैं ; अर्थात्, वे एक ही वस्तु को संदर्भित करते हैं।
वस्तु समानता : जब आप दो वस्तुओं की तुलना करते हैं, तो आप आमतौर पर ध्यान नहीं देते हैं कि यह स्मृति में सटीक समान ऑब्जेक्ट को संदर्भित करता है । वस्तु समानता के साथ, आप दो वस्तुओं की तुलना कैसे करते हैं, इसके लिए आप अपने स्वयं के नियमों को परिभाषित कर सकते हैं। जब आप लिखते हैं if a == b:
, आप अनिवार्य रूप से कह रहे हैं if a.__eq__(b):
। यह आपको एक __eq__
विधि को परिभाषित करने देता है a
ताकि आप अपने स्वयं के तुलना तर्क का उपयोग कर सकें।
औचित्य: दो वस्तुओं में एक ही डेटा होता है, लेकिन समान नहीं होते हैं। (वे स्मृति में एक ही वस्तु नहीं हैं।) उदाहरण: स्ट्रिंग्स
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
नोट: मैं यहां यूनिकोड स्ट्रिंग्स का उपयोग करता हूं, क्योंकि पायथन काफी स्मार्ट है, जो नियमित स्ट्रिंग्स को फिर से उपयोग किए बिना मेमोरी में बनाता है।
यहाँ, मेरे पास दो यूनिकोड स्ट्रिंग्स हैं, a
और b
। उनके पास समान सामग्री है, लेकिन वे स्मृति में समान वस्तु नहीं हैं। हालांकि, जब हम उनकी तुलना करते हैं, तो हम चाहते हैं कि वे बराबर की तुलना करें। यहाँ क्या हो रहा है कि यूनिकोड ऑब्जेक्ट ने __eq__
विधि को लागू किया है।
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in zip(self, other):
if i != j:
return False
return True
नोट: निश्चित रूप से इस से अधिक कुशलता से लागू __eq__
किया unicode
जाता है।
Rationale: दो वस्तुओं के अलग-अलग डेटा होते हैं, लेकिन यदि कुछ प्रमुख डेटा समान हों तो उन्हें एक ही वस्तु माना जाता है। उदाहरण: अधिकांश प्रकार के मॉडल डेटा
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
यहाँ, मेरे पास दो डेल मॉनिटर हैं, a
और b
। उनके पास एक ही मेक और मॉडल है। हालाँकि, उनके पास न तो समान डेटा है और न ही मेमोरी में समान ऑब्जेक्ट हैं। हालांकि, जब हम उनकी तुलना करते हैं, तो हम चाहते हैं कि वे बराबर की तुलना करें। यहाँ क्या हो रहा है कि मॉनिटर ऑब्जेक्ट ने __eq__
विधि को लागू किया ।
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
तुलना करते समय None
, हमेशा उपयोग करें is not
। पायथन में कोई भी एकल नहीं है - स्मृति में इसका केवल एक उदाहरण है।
पहचान की तुलना करके , यह बहुत जल्दी प्रदर्शन किया जा सकता है। पायथन यह जाँचता है कि जिस ऑब्जेक्ट का आप उल्लेख कर रहे हैं, उसमें वैसा ही मेमोरी एड्रेस है जैसा कि वैश्विक कोई भी वस्तु नहीं है - दो नंबरों की तुलना में बहुत तेज।
समानता की तुलना करके , पायथन को यह देखना होगा कि आपकी वस्तु में कोई __eq__
विधि है या नहीं। यदि ऐसा नहीं होता है, तो यह एक __eq__
विधि की तलाश में प्रत्येक सुपरक्लास की जांच करता है । यदि यह एक पाता है, तो पायथन इसे कहता है। यह विशेष रूप से बुरा है यदि __eq__
विधि धीमी है और तुरंत वापस नहीं आती है जब यह नोटिस करता है कि दूसरी वस्तु है None
।
आपने लागू नहीं किया __eq__
? तब पायथन संभवत: इस __eq__
पद्धति को खोजेगा object
और इसके बजाय इसका उपयोग करेगा - जो कि वैसे भी वस्तु पहचान के लिए जांच करता है।
पायथन में अधिकांश अन्य चीजों की तुलना करते समय, आप उपयोग कर रहे होंगे !=
।
निम्नलिखित को धयान मे रखते हुए:
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
None
एक सिंगलटन है, इसलिए पहचान की तुलना हमेशा काम करेगी, जबकि एक वस्तु समानता तुलना के माध्यम से नकली हो सकती है .__eq__()
।
None
, लेकिन None
अन्य प्रकार के खिलाफ समानता को लागू करने के दुष्प्रभाव के रूप में गलत व्यवहार हो सकता है। यह इतना सुरक्षा निहितार्थ नहीं है क्योंकि यह सिर्फ शुद्धता निहितार्थ है।
>>> () है () सच >>> 1 1 है सच >>> (1,) == (1,) सच >>> (1,) है (1,) असत्य >>> ए = (1) >>> बी = ए >>> ए बी है सच
कुछ ऑब्जेक्ट एकल हैं, और इस तरह is
उनके साथ समतुल्य है ==
। ज्यादातर नहीं हैं।
()
और 1
स्वाभाविक रूप से एकल नहीं हैं।
-NSMALLNEGINTS <= n <= NSMALLPOSINTS
) और खाली ट्यूपल एकल हैं । वास्तव में यह न तो प्रलेखित है और न ही इसकी गारंटी है, लेकिन यह बदलने की संभावना नहीं है।