在Python 中,自訂類別可以實作__eq__ 和__ne__ 方法來定義== 和!= 運算子的等價性,分別。雖然比較字典屬性的傳統方法很簡單,但它有一定的限制。
考慮以下場景:
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
解決此問題,我們可以重寫__eq__ 方法:
class Number: def __init__(self, number): self.number = number def __eq__(self, other): if isinstance(other, Number): return self.number == other.number return False
但是,對於Python 2,我們還需要實作__ne__來確保交換行為:
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)
這確保 n1 == n2計算結果為 True,如預期。
引入子類會使等效比較複雜化:
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
對於經典樣式的類,根據第一個操作數的類型,導致非交換行為。為了解決這個問題,我們可以為不支援的運算元類型傳回NotImplemented,它將比較委託給其他運算元的方法:
def __eq__(self, other): if isinstance(other, Number): return self.number == other.number return NotImplemented
最後,請請注意,集合使用物件標識符哈希,這可能會導致不正確的結果:
assert len(set([n1, n2, n3])) == 3 # Incorrectly reports 3 unique numbers
要解決此問題,我們可以重寫__hash__ 方法:
def __hash__(self): return hash(tuple(sorted(self.__dict__.items())))
透過這些增強功能,等價性和唯一性行為變得正確,並且一致,確保集合中的穩健比較和準確表示:
assert len(set([n1, n2, n3])) == 1 assert len(set([n1, n2, n3, n4])) == 2
以上是如何確保自訂 Python 類別的一致且穩健的等價比較,尤其是在處理子類別和集合時?的詳細內容。更多資訊請關注PHP中文網其他相關文章!