यह इस बात का एक बड़ा उदाहरण है कि __dunder__तरीकों का सीधे उपयोग क्यों नहीं किया जाना चाहिए क्योंकि वे अपने समकक्ष ऑपरेटरों के लिए अक्सर उपयुक्त प्रतिस्थापन नहीं होते हैं; आपको ==समानता की तुलना के लिए ऑपरेटर का उपयोग करना चाहिए , या इस विशेष मामले में, जांच करते समय None, उपयोग करें is(अधिक जानकारी के लिए उत्तर के नीचे की ओर छोड़ें)।
तुमने कर दिया
None.__eq__('a')
# NotImplemented
NotImplementedतुलना के प्रकार भिन्न होने के बाद से जो रिटर्न मिलता है । एक और उदाहरण पर विचार करें, जहां इस प्रकार की दो वस्तुओं की तुलना इस प्रकार की जा रही है, जैसे कि 1और 'a'। करना (1).__eq__('a')भी सही नहीं है, और वापस आ जाएगा NotImplemented। समानता के लिए इन दो मूल्यों की तुलना करने का सही तरीका होगा
1 == 'a'
# False
यहां क्या होता है
- सबसे पहले,
(1).__eq__('a')कोशिश की जाती है, जो वापस आती है NotImplemented। यह इंगित करता है कि ऑपरेशन समर्थित नहीं है, इसलिए
'a'.__eq__(1)कहा जाता है, जो भी लौटाता है NotImplemented। इसलिए,
- वस्तुओं के साथ ऐसा व्यवहार किया जाता है जैसे कि वे एक जैसी न हों, और
Falseवापस आ जाएं।
यह कैसे होता है, यह बताने के लिए कुछ कस्टम कक्षाओं का उपयोग करके एक अच्छा सा MCVE दिया गया है:
class A:
def __eq__(self, other):
print('A.__eq__')
return NotImplemented
class B:
def __eq__(self, other):
print('B.__eq__')
return NotImplemented
class C:
def __eq__(self, other):
print('C.__eq__')
return True
a = A()
b = B()
c = C()
print(a == b)
# A.__eq__
# B.__eq__
# False
print(a == c)
# A.__eq__
# C.__eq__
# True
print(c == a)
# C.__eq__
# True
बेशक, यह स्पष्ट नहीं करता है कि ऑपरेशन सही क्यों है। ऐसा इसलिए है क्योंकि NotImplementedवास्तव में एक सत्य मूल्य है:
bool(None.__eq__("a"))
# True
के समान,
bool(NotImplemented)
# True
सत्य और असत्य माना जाने वाले मूल्यों के बारे में अधिक जानकारी के लिए, सत्य मान परीक्षण पर डॉक्स अनुभाग और साथ ही इस उत्तर को देखें । यहां यह ध्यान देने योग्य है कि है NotImplementedtruthy है, लेकिन यह किया गया है एक अलग कहानी वर्ग एक परिभाषित किया था होगा __bool__या __len__विधि कि लौट आए Falseया 0क्रमशः।
यदि आप ==ऑपरेटर के कार्यात्मक समकक्ष चाहते हैं , तो उपयोग करें operator.eq:
import operator
operator.eq(1, 'a')
# False
हालाँकि, जैसा कि पहले उल्लेख किया गया है, इस विशिष्ट परिदृश्य के लिए , जहाँ आप Noneउपयोग कर रहे हैं is:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
इसके समतुल्य कार्यात्मक उपयोग कर रहा है operator.is_:
operator.is_(var2, None)
# True
Noneएक विशेष वस्तु है, और किसी भी समय स्मृति में केवल 1 संस्करण मौजूद है। IOW, यह NoneTypeवर्ग का एकमात्र सिंगलटन है (लेकिन एक ही वस्तु में किसी भी संख्या में संदर्भ हो सकते हैं)। PEP8 दिशा निर्देशों इस स्पष्ट हो जाता है:
Noneहमेशा की तरह एकल ऑपरेटरों के साथ तुलना की जानी चाहिए isया
is notकभी नहीं, समानता ऑपरेटरों।
सारांश में, जैसे एकल के लिए None, के साथ एक संदर्भ जांच isअधिक उपयुक्त है, हालांकि दोनों ==और isबस ठीक काम करेगा।