Heim >Backend-Entwicklung >Python-Tutorial >Wie stellen Sie konsistente und robuste Äquivalenzvergleiche für benutzerdefinierte Python-Klassen sicher, insbesondere beim Umgang mit Unterklassen und Mengen?
In Python können benutzerdefinierte Klassen die Methoden __eq__ und __ne__ implementieren, um Äquivalenz für die Operatoren == und != zu definieren. jeweils. Obwohl die herkömmliche Methode zum Vergleichen von Wörterbuchattributen unkompliziert ist, weist sie gewisse Einschränkungen auf.
Stellen Sie sich das folgende Szenario vor:
class Number: def __init__(self, number): self.number = number n1 = Number(1) n2 = Number(1) # Default comparison fails: they are different objects assert n1 != n2
Um dieses Problem zu beheben , wir können die __eq__-Methode überschreiben:
class Number: def __init__(self, number): self.number = number def __eq__(self, other): if isinstance(other, Number): return self.number == other.number return False
Für Python 2 müssen wir jedoch auch implementieren __ne__, um kommutatives Verhalten sicherzustellen:
class Number: def __init__(self, number): self.number = number def __eq__(self, other): if isinstance(other, Number): return self.number == other.number return False def __ne__(self, other): return not self.__eq__(other)
Dadurch wird sichergestellt, dass n1 == n2 erwartungsgemäß „True“ ergibt.
Die Einführung von Unterklassen erschwert den Äquivalenzvergleich:
class SubNumber(Number): pass n3 = SubNumber(1) # Subclass comparison fails for classic-style classes assert n1 == n3 # False (for classic-style classes) assert n3 == n1 # True # Non-commutative comparison assert n1 != n3 # True (for classic-style classes) assert n3 != n1 # False
Für Klassen im klassischen Stil wird die Vergleichsmethode basierend auf aufgerufen Der Typ des ersten Operanden führt zu nicht kommutativem Verhalten. Um dies zu beheben, können wir NotImplemented für nicht unterstützte Operandentypen zurückgeben, wodurch der Vergleich an die Methode des anderen Operanden delegiert wird:
def __eq__(self, other): if isinstance(other, Number): return self.number == other.number return NotImplemented
Zuletzt beachten Sie, dass Sets Objektbezeichner für verwenden Hashing, das zu falschen Ergebnissen führen kann:
assert len(set([n1, n2, n3])) == 3 # Incorrectly reports 3 unique numbers
Um dieses Problem zu beheben, können wir das überschreiben __hash__-Methode:
def __hash__(self): return hash(tuple(sorted(self.__dict__.items())))
Mit diesen Verbesserungen wird das Äquivalenz- und Eindeutigkeitsverhalten korrekt und konsistent, was robuste Vergleiche und eine genaue Darstellung in Mengen gewährleistet:
assert len(set([n1, n2, n3])) == 1 assert len(set([n1, n2, n3, n4])) == 2
Das obige ist der detaillierte Inhalt vonWie stellen Sie konsistente und robuste Äquivalenzvergleiche für benutzerdefinierte Python-Klassen sicher, insbesondere beim Umgang mit Unterklassen und Mengen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!