अजगर वर्गों में तुल्यता ("समानता") का समर्थन करने के लिए सुरुचिपूर्ण तरीके


421

कस्टम कक्षाएं लिखते समय अक्सर ==और !=ऑपरेटरों के माध्यम से तुल्यता की अनुमति देना महत्वपूर्ण होता है । पायथन में , क्रमशः __eq__और __ne__विशेष विधियों को लागू करके इसे संभव बनाया गया है। ऐसा करने का सबसे आसान तरीका निम्नलिखित तरीका है:

class Foo:
    def __init__(self, item):
        self.item = item

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False

    def __ne__(self, other):
        return not self.__eq__(other)

क्या आप इसे करने के अधिक सुरुचिपूर्ण साधनों के बारे में जानते हैं? क्या आप __dict__एस की तुलना करने के उपरोक्त तरीके का उपयोग करने के लिए किसी विशेष नुकसान के बारे में जानते हैं ?

नोट : स्पष्टीकरण के एक बिट - जब __eq__और __ne__अपरिभाषित हैं, तो आपको यह व्यवहार मिलेगा:

>>> a = Foo(1)
>>> b = Foo(1)
>>> a is b
False
>>> a == b
False

यही है, a == bमूल्यांकन करता है Falseक्योंकि यह वास्तव में चलता है a is b, पहचान की एक परीक्षा (यानी, "क्या aवही वस्तु है b?")।

जब __eq__और __ne__परिभाषित कर रहे हैं, तो आप इस व्यवहार मिल जाएगा (जो एक हम के बाद कर रहे हैं है):

>>> a = Foo(1)
>>> b = Foo(1)
>>> a is b
False
>>> a == b
True

6
+1, क्योंकि मुझे नहीं पता था कि == के लिए तानाशाह ने सदृश समानता का इस्तेमाल किया था, मैंने मान लिया था कि यह केवल उन्हें एक ही वस्तु के बराबर के बराबर गिना जाता है। मुझे लगता है कि यह स्पष्ट है क्योंकि पायथन के पास isमूल्य तुलना से वस्तु पहचान को अलग करने के लिए ऑपरेटर है।
सिंगलएनजेशन इलिमिनेशन

5
मुझे लगता है कि स्वीकार किए गए उत्तर को सही किया जा सकता है या अल्गोरियस के जवाब पर भरोसा किया जाता है, ताकि सख्त प्रकार की जांच को लागू किया जाए।
अधिकतम

1
यह भी सुनिश्चित करें कि हैश को ओवरराइड किया गया है stackoverflow.com/questions/1608842/…
एलेक्स पुन्नन

जवाबों:


328

इस साधारण समस्या पर विचार करें:

class Number:

    def __init__(self, number):
        self.number = number


n1 = Number(1)
n2 = Number(1)

n1 == n2 # False -- oops

इसलिए, डिफ़ॉल्ट रूप से पायथन तुलनात्मक संचालन के लिए वस्तु पहचानकर्ताओं का उपयोग करता है:

id(n1) # 140400634555856
id(n2) # 140400634555920

__eq__फ़ंक्शन को ओवरराइड करने से समस्या का समाधान होता है:

def __eq__(self, other):
    """Overrides the default implementation"""
    if isinstance(other, Number):
        return self.number == other.number
    return False


n1 == n2 # True
n1 != n2 # True in Python 2 -- oops, False in Python 3

में अजगर 2 , हमेशा ओवरराइड करने के लिए याद __ne__के साथ-साथ समारोह, के रूप में प्रलेखन कहता है:

तुलना ऑपरेटरों के बीच कोई निहित संबंध नहीं हैं। सत्य का x==yअर्थ x!=yअसत्य नहीं है । तदनुसार, परिभाषित करते समय __eq__(), एक को भी परिभाषित करना चाहिए __ne__()ताकि ऑपरेटर अपेक्षा के अनुरूप व्यवहार करेंगे।

def __ne__(self, other):
    """Overrides the default implementation (unnecessary in Python 3)"""
    return not self.__eq__(other)


n1 == n2 # True
n1 != n2 # False

में अजगर 3 , अब यह आवश्यक है, के रूप में प्रलेखन कहता है:

डिफ़ॉल्ट रूप से, जब तक यह नहीं होता है तब तक परिणाम को दर्शाता __ne__()है __eq__()और इनवर्ट करता है NotImplemented। तुलना ऑपरेटरों के बीच कोई अन्य निहित संबंध नहीं हैं, उदाहरण के लिए, सच्चाई का (x<y or x==y)मतलब नहीं है x<=y

लेकिन वह हमारी सभी समस्याओं को हल नहीं करता है। चलो एक उपवर्ग जोड़ें:

class SubNumber(Number):
    pass


n3 = SubNumber(1)

n1 == n3 # False for classic-style classes -- oops, True for new-style classes
n3 == n1 # True
n1 != n3 # True for classic-style classes -- oops, False for new-style classes
n3 != n1 # False

नोट: अजगर 2 में दो प्रकार की कक्षाएं हैं:

  • क्लासिक-शैली (या पुरानी-शैली ) कक्षाएं, जोइनहेरिट नहींobject करती हैं और जिन्हें घोषित किया जाता हैclass A:,class A():याclass A(B):जहांBएक क्लासिक-शैली वर्ग है;

  • नई शैली की कक्षाएं, जो इनहेरिट करती हैंobjectऔर जिन्हेंनए शैली वर्ग केरूप मेंclass A(object)याclass A(B):जहांघोषित किया जाताBहै। पायथन 3 में केवल नई-शैली की कक्षाएं हैं जिन्हें घोषित किया गया हैclass A:,class A(object):याclass A(B):

क्लासिक-शैली की कक्षाओं के लिए, एक तुलना ऑपरेशन हमेशा पहले ऑपरेंड की विधि को कहता है, जबकि नई-शैली की कक्षाओं के लिए, यह हमेशा ऑपरेंड के आदेश की परवाह किए बिना , उप-वर्ग ऑपरेंड की विधि को कॉल करता है

यहाँ है, अगर Numberएक क्लासिक शैली वर्ग है:

  • n1 == n3कॉल करता है n1.__eq__;
  • n3 == n1कॉल करता है n3.__eq__;
  • n1 != n3कॉल करता है n1.__ne__;
  • n3 != n1कॉल करता है n3.__ne__

और अगर Numberएक नई शैली वर्ग है:

  • दोनों n1 == n3और n3 == n1बुलाओ n3.__eq__;
  • दोनों n1 != n3और n3 != n1बुलाओ n3.__ne__

पायथन 2 क्लासिक शैली की कक्षाओं के लिए ==और !=ऑपरेटरों के गैर-कम्यूटेटिविटी मुद्दे को ठीक करने के लिए, __eq__और __ne__तरीकों को उस NotImplementedमूल्य को वापस करना चाहिए जब एक ऑपरेंड प्रकार समर्थित नहीं है। प्रलेखन को परिभाषित करता है NotImplementedके रूप में मूल्य:

यदि वे प्रदान किए गए ऑपरेंड के संचालन को कार्यान्वित नहीं करते हैं तो संख्यात्मक विधियां और समृद्ध तुलना विधियां इस मान को लौटा सकती हैं। (दुभाषिया फिर ऑपरेटर के आधार पर परिलक्षित ऑपरेशन, या कुछ अन्य कमियां की कोशिश करेगा।) इसका सत्य मूल्य सत्य है।

इस मामले में ऑपरेटर दूसरे ऑपरेंड की परिलक्षित विधि के लिए तुलना ऑपरेशन को दर्शाता हैप्रलेखन परिभाषित करता है के रूप में परिलक्षित तरीके:

इन तरीकों का कोई स्वैप-तर्क संस्करण नहीं है (जब बाएं तर्क ऑपरेशन का समर्थन नहीं करता है लेकिन सही तर्क करता है); बल्कि, __lt__()और __gt__()एक-दूसरे के प्रतिबिंब हैं, __le__()और __ge__()एक-दूसरे के प्रतिबिंब हैं, और __eq__()और __ne__()अपने स्वयं के प्रतिबिंब हैं।

परिणाम इस तरह दिखता है:

def __eq__(self, other):
    """Overrides the default implementation"""
    if isinstance(other, Number):
        return self.number == other.number
    return NotImplemented

def __ne__(self, other):
    """Overrides the default implementation (unnecessary in Python 3)"""
    x = self.__eq__(other)
    if x is NotImplemented:
        return NotImplemented
    return not x

रिटर्निंग NotImplementedके बजाय मूल्य Falseअगर नई शैली कक्षाओं के लिए भी ऐसा करना सही है commutativity की ==और !=ऑपरेटरों जब ऑपरेंड असंबंधित प्रकार (कोई विरासत) के हैं वांछित है।

क्या हम अब भी वहां हैं? काफी नहीं। हमारे पास कितने विशिष्ट नंबर हैं?

len(set([n1, n2, n3])) # 3 -- oops

सेट ऑब्जेक्ट्स के हैश का उपयोग करते हैं, और डिफ़ॉल्ट रूप से पायथन ऑब्जेक्ट के पहचानकर्ता का हैश लौटाता है। आइए इसे ओवरराइड करने का प्रयास करें:

def __hash__(self):
    """Overrides the default implementation"""
    return hash(tuple(sorted(self.__dict__.items())))

len(set([n1, n2, n3])) # 1

अंतिम परिणाम इस तरह दिखता है (मैंने सत्यापन के लिए अंत में कुछ दावे जोड़े):

class Number:

    def __init__(self, number):
        self.number = number

    def __eq__(self, other):
        """Overrides the default implementation"""
        if isinstance(other, Number):
            return self.number == other.number
        return NotImplemented

    def __ne__(self, other):
        """Overrides the default implementation (unnecessary in Python 3)"""
        x = self.__eq__(other)
        if x is not NotImplemented:
            return not x
        return NotImplemented

    def __hash__(self):
        """Overrides the default implementation"""
        return hash(tuple(sorted(self.__dict__.items())))


class SubNumber(Number):
    pass


n1 = Number(1)
n2 = Number(1)
n3 = SubNumber(1)
n4 = SubNumber(4)

assert n1 == n2
assert n2 == n1
assert not n1 != n2
assert not n2 != n1

assert n1 == n3
assert n3 == n1
assert not n1 != n3
assert not n3 != n1

assert not n1 == n4
assert not n4 == n1
assert n1 != n4
assert n4 != n1

assert len(set([n1, n2, n3, ])) == 1
assert len(set([n1, n2, n3, n4])) == 2

3
hash(tuple(sorted(self.__dict__.items())))काम नहीं करेगा यदि मूल्यों के बीच कोई भी गैर-धोने योग्य वस्तुएं हैं self.__dict__(यानी, यदि ऑब्जेक्ट की कोई विशेषता सेट की जाती है, तो, कहो list)।
अधिकतम

3
सच है, लेकिन तब अगर आपके पास ऐसी भिन्न वस्तुएं हैं जो आपके var () में दो वस्तुएं वास्तव में समान नहीं हैं ...
Tal Weiss


1
तीन टिप्पणियां: 1. पायथन 3 में, __ne__अब और लागू करने की कोई आवश्यकता नहीं है: "डिफ़ॉल्ट रूप से, परिणाम को दर्शाता __ne__()है __eq__()और तब तक पलट देता है जब तक कि यह न हो NotImplemented"। 2. एक अभी भी लागू करने के लिए चाहता है __ne__, एक अधिक सामान्य कार्यान्वयन (अजगर 3 मुझे लगता है कि द्वारा प्रयोग किया जाता है): x = self.__eq__(other); if x is NotImplemented: return x; else: return not x। 3. दी गई __eq__और __ne__कार्यान्वितियाँ सब-टोटल हैं: if isinstance(other, type(self)):22 __eq__और 10 __ne__कॉल देती हैं, जबकि if isinstance(self, type(other)):16 __eq__और 6 __ne__कॉल देती हैं।
मैगीयरो

4
उन्होंने शान के बारे में पूछा, लेकिन वे मजबूत हो गए।
ग्रेगनाश

201

आपको विरासत से सावधान रहने की जरूरत है:

>>> class Foo:
    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False

>>> class Bar(Foo):pass

>>> b = Bar()
>>> f = Foo()
>>> f == b
True
>>> b == f
False

इस तरह से और अधिक सख्ती से जाँच करें:

def __eq__(self, other):
    if type(other) is type(self):
        return self.__dict__ == other.__dict__
    return False

इसके अलावा, आपका दृष्टिकोण ठीक काम करेगा, यही खास तरीके हैं।


यह लाभप्रद है। मुझे लगता है कि यह ध्यान देने योग्य है कि प्रकारों में निर्मित उप-क्लासिंग अभी भी समानता के लिए दिशा की अनुमति देता है, और इसलिए यह जांचना कि यह उसी प्रकार का है अवांछनीय भी हो सकता है।
21

12
यदि आरएचएस की तुलना को दर्शाते हुए, प्रकार अलग-अलग हैं, तो मैं NotImplemented लौटने का सुझाव दूंगा।
अधिकतम

4
@ मुख्य तुलना बाएं हाथ की ओर (LHS) से दाएं हाथ की ओर (RHS), तो RHS से LHS तक नहीं की जाती है; देख stackoverflow.com/a/12984987/38140 । फिर भी, NotImplementedजैसा कि आप सुझाव देते हैं superclass.__eq__(subclass), हमेशा लौटना होगा , जो कि वांछित व्यवहार है।
gotgenes

4
यदि आपके पास सदस्यों की एक टन है, और आस-पास बैठे कई ऑब्जेक्ट प्रतियां नहीं हैं, तो यह आमतौर पर एक प्रारंभिक पहचान परीक्षा में अच्छा होता है if other is self। यह अधिक लंबी शब्दकोश तुलना से बचा जाता है, और वस्तुओं की शब्दकोष के रूप में उपयोग किए जाने पर एक बड़ी बचत हो सकती है।
डेन व्हाइट

2
और लागू करने के लिए मत भूलना__hash__()
डेन व्हाइट

161

जिस तरह से आप वर्णन करते हैं वह तरीका है जो मैंने हमेशा किया है। चूंकि यह पूरी तरह से सामान्य है, आप हमेशा उस कार्यक्षमता को मिक्स्ड क्लास में तोड़ सकते हैं और इसे उन कक्षाओं में विरासत में प्राप्त कर सकते हैं जहाँ आप उस कार्यक्षमता को चाहते हैं।

class CommonEqualityMixin(object):

    def __eq__(self, other):
        return (isinstance(other, self.__class__)
            and self.__dict__ == other.__dict__)

    def __ne__(self, other):
        return not self.__eq__(other)

class Foo(CommonEqualityMixin):

    def __init__(self, item):
        self.item = item

6
+1: उपवर्गों में आसान प्रतिस्थापन की अनुमति देने के लिए रणनीति पैटर्न।
S.Lott

3
आइंस्टीन चूसता है। इसकी जांच क्यों? केवल स्व .__ तानाशाही == अन्य .__ तानाशाही क्यों नहीं?
nosklo 18

3
@nosklo: मुझे समझ में नहीं आता है .. क्या होगा अगर पूरी तरह से असंबंधित वर्गों से दो वस्तुओं में समान गुण होते हैं?
अधिकतम

1
मुझे लगा कि नोक्सलो ने सुझाव दिया है कि स्किपिंग आइंस्टीन है। उस मामले में अब आपको पता नहीं है कि क्या otherउपवर्ग का है self.__class__
अधिकतम

10
__dict__तुलना के साथ एक और मुद्दा यह है कि यदि आपके पास एक विशेषता है जिसे आप समानता की अपनी परिभाषा में विचार नहीं करना चाहते हैं (उदाहरण के लिए एक अद्वितीय ऑब्जेक्ट आईडी, या मेटाडेटा जैसे समय निर्मित स्टैंप)।
एडम पार्किन

14

प्रत्यक्ष उत्तर नहीं, लेकिन पर्याप्त प्रासंगिक लग रहा था, क्योंकि इस अवसर पर कुछ क्रियात्मक टेडियम से बचा जाता है। डॉक्स से सीधे कट ...


functools.total_ordering (सीएलएस)

एक या एक से अधिक समृद्ध तुलना क्रम विधियों को परिभाषित करने वाले वर्ग को देखते हुए, यह वर्ग सज्जाकार बाकी की आपूर्ति करता है। यह संभव समृद्ध तुलनात्मक संचालन के सभी को निर्दिष्ट करने में शामिल प्रयास को सरल करता है:

वर्ग में से एक को परिभाषित करना होगा __lt__(), __le__(), __gt__(), या __ge__()। इसके अलावा, वर्ग को एक __eq__()विधि की आपूर्ति करनी चाहिए ।

संस्करण 2.7 में नया

@total_ordering
class Student:
    def __eq__(self, other):
        return ((self.lastname.lower(), self.firstname.lower()) ==
                (other.lastname.lower(), other.firstname.lower()))
    def __lt__(self, other):
        return ((self.lastname.lower(), self.firstname.lower()) <
                (other.lastname.lower(), other.firstname.lower()))

1
हालाँकि कुल_ऑर्डरिंग में सूक्ष्म नुकसान होते हैं: regebro.wordpress.com/2010/12/13/… । जागरूक रहें !
Mr_and_Mrs_D

8

आपको दोनों को ओवरराइड नहीं करना है __eq__ और __ne__आप केवल ओवरराइड कर सकते हैं, __cmp__लेकिन इससे ==, =! ==, <,> और इसी तरह के परिणाम पर प्रभाव पड़ेगा।

isवस्तु पहचान के लिए परीक्षण। इसका अर्थ यह है कि isb Trueउस स्थिति में होगा जब a और b दोनों एक ही वस्तु के संदर्भ को धारण करते हैं। अजगर में आप हमेशा एक वस्तु के संदर्भ को एक चर में रखते हैं वास्तविक वस्तु नहीं, इसलिए अनिवार्य रूप से एक ख के लिए सही है कि वस्तुओं को एक ही स्मृति स्थान में स्थित होना चाहिए। इस व्यवहार को ओवरराइड करने के बारे में आप कैसे और सबसे महत्वपूर्ण बात क्यों करेंगे?

संपादित करें: मुझे नहीं पता __cmp__था कि अजगर 3 से हटा दिया गया था इसलिए इसे से बचें।


क्योंकि कभी-कभी आपकी वस्तुओं के लिए समानता की एक अलग परिभाषा होती है।
एड एस।

क्या आपरेटर व्याख्याकारों को वस्तु पहचान का उत्तर देता है, लेकिन आप अभी भी सीएमपी
Vasil

7
पायथन 3 में, "cmp () फ़ंक्शन चला गया है, और __cmp __ () विशेष विधि समर्थित नहीं है।" is.gd/aeGv
gotgenes

4

इस उत्तर से: https://stackoverflow.com/a/30676267/541136 मैंने इसे प्रदर्शित किया है, जबकि इसे __ne__शब्दों में परिभाषित करना सही है__eq__ - बजाय

def __ne__(self, other):
    return not self.__eq__(other)

आपको उपयोग करना चाहिए:

def __ne__(self, other):
    return not self == other

2

मुझे लगता है कि जिन दो शब्दों को आप देख रहे हैं वे समानता (==) और पहचान (हैं) हैं। उदाहरण के लिए:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> a == b
True       <-- a and b have values which are equal
>>> a is b
False      <-- a and b are not the same list object

1
हो सकता है, सिवाय इसके कि कोई एक वर्ग बना सकता है जो केवल दो सूचियों में पहले दो वस्तुओं की तुलना करता है, और यदि वे आइटम समान हैं, तो यह True का मूल्यांकन करता है। यह समानता है, मुझे लगता है, समानता नहीं। अभी भी eq में पूरी तरह से मान्य है ।
gotgenes

मैं सहमत हूं, हालांकि, यह "पहचान" एक परीक्षण है।
gotgenes

1

अंतर्निहित 'आईडी ()' फ़ंक्शन का उपयोग करके पहचान के लिए 'परीक्षण' परीक्षण होगा जो अनिवार्य रूप से ऑब्जेक्ट का मेमोरी एड्रेस लौटाता है और इसलिए अधिभार नहीं है।

हालाँकि एक वर्ग की समानता के परीक्षण के मामले में आप शायद अपने परीक्षणों के बारे में थोड़ा और सख्त होना चाहते हैं और केवल अपनी कक्षा में डेटा विशेषताओं की तुलना करें:

import types

class ComparesNicely(object):

    def __eq__(self, other):
        for key, value in self.__dict__.iteritems():
            if (isinstance(value, types.FunctionType) or 
                    key.startswith("__")):
                continue

            if key not in other.__dict__:
                return False

            if other.__dict__[key] != value:
                return False

         return True

यह कोड केवल आपकी कक्षा के गैर-फ़ंक्शन डेटा सदस्यों की तुलना करेगा और साथ ही कुछ भी निजी तौर पर छोड़ देगा जो कि आम तौर पर आप चाहते हैं। प्लेन ओल्ड पायथन ऑब्जेक्ट्स के मामले में मेरे पास एक बेस क्लास है जो __init__, __str__, __repr__ और __eq__ को लागू करता है इसलिए मेरी POPO ऑब्जेक्ट्स उस अतिरिक्त (और अधिकांश मामलों में समान) लॉजिक का बोझ नहीं उठाती हैं।


बिट नाइटपिकी, लेकिन आईडी '() का उपयोग करके परीक्षण केवल तभी होता है जब आपने अपना स्वयं का is_ () सदस्य फ़ंक्शन (2.3+) परिभाषित नहीं किया है। [ Docs.python.org/library/operator.html]
spenthil

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

mcrute - मैंने बहुत जल्द (और गलत तरीके से) बात की, आप बिल्कुल सही हैं।
बिताए गए

यह एक बहुत अच्छा समाधान है, विशेष रूप से जब __eq__वसीयत में घोषित किया जाएगा CommonEqualityMixin(अन्य उत्तर देखें)। SQLAlchemy में बेस से ली गई कक्षाओं के उदाहरणों की तुलना करते समय मुझे यह विशेष रूप से उपयोगी लगा। तुलना न करने के लिए _sa_instance_stateमैं बदल key.startswith("__")):गया key.startswith("_")):। मेरे पास उनमें कुछ बैकरेफरेंस भी थे और अल्गोरियस के उत्तर ने अंतहीन पुनरावृत्ति उत्पन्न की। इसलिए मैंने सभी बैकरेफरेंस की शुरुआत की, '_'ताकि वे भी तुलना के दौरान रुक जाएं। नोट: अजगर 3.x परिवर्तन में iteritems()करने के लिए items()
वूकी88

@mcrute आमतौर पर, __dict__उदाहरण के लिए कुछ भी नहीं है जो __तब तक शुरू होता है जब तक कि उपयोगकर्ता द्वारा परिभाषित नहीं किया गया हो। चीजों की तरह __class__, __init__आदि उदाहरण के में नहीं हैं __dict__, बल्कि अपनी श्रेणी में ' __dict__। OTOH, निजी विशेषताओं के साथ आसानी से शुरू हो सकता है __और शायद इसके लिए उपयोग किया जाना चाहिए __eq__। क्या आप स्पष्ट कर सकते हैं कि __स्किप -प्रूफ किए गए विशेषताओं को छोड़ते समय आप वास्तव में क्या करना चाह रहे थे ?
अधिकतम

1

उपवर्ग / मिश्रण का उपयोग करने के बजाय, मैं एक सामान्य श्रेणी के डेकोरेटर का उपयोग करना पसंद करता हूं

def comparable(cls):
    """ Class decorator providing generic comparison functionality """

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not self.__eq__(other)

    cls.__eq__ = __eq__
    cls.__ne__ = __ne__
    return cls

उपयोग:

@comparable
class Number(object):
    def __init__(self, x):
        self.x = x

a = Number(1)
b = Number(1)
assert a == b

0

यह अल्गोरियस के उत्तर पर टिप्पणियों को शामिल करता है, और वस्तुओं की तुलना एक ही विशेषता से करता है क्योंकि मुझे पूरे तानाशाह की परवाह नहीं है। hasattr(other, "id")यह सच होना चाहिए, लेकिन मुझे पता है कि मैं इसे कंस्ट्रक्टर में सेट करता हूं।

def __eq__(self, other):
    if other is self:
        return True

    if type(other) is not type(self):
        # delegate to superclass
        return NotImplemented

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