[英]Overriding __eq__ and __hash__ to compare a dict attribute of two instances
我正在努力了解如何根據每個實例具有的基礎dict屬性正確比較對象。
由於我要覆蓋__eq__
,是否還需要覆蓋__hash__
? 我不確定何時/何地這樣做,真的可以使用一些幫助。
我在下面創建了一個簡單的示例,以說明遇到的最大遞歸異常。 RegionalCustomerCollection
按地理RegionalCustomerCollection
組織帳戶ID。 如果區域及其各自的accountid
是相同的,則可以說RegionalCustomerCollection
對象是相等的。 本質上,所有items()
內容都應該相等。
from collections import defaultdict
class RegionalCustomerCollection(object):
def __init__(self):
self.region_accountids = defaultdict(set)
def get_region_accountid(self, region_name=None):
return self.region_accountids.get(region_name, None)
def set_region_accountid(self, region_name, accountid):
self.region_accountids[region_name].add(accountid)
def __eq__(self, other):
if (other == self):
return True
if isinstance(other, RegionalCustomerCollection):
return self.region_accountids == other.region_accountids
return False
def __repr__(self):
return ', '.join(["{0}: {1}".format(region, acctids)
for region, acctids
in self.region_accountids.items()])
讓我們創建兩個對象實例,並用一些示例數據填充它們:
>>> a = RegionalCustomerCollection()
>>> b = RegionalCustomerCollection()
>>> a.set_region_accountid('northeast',1)
>>> a.set_region_accountid('northeast',2)
>>> a.set_region_accountid('northeast',3)
>>> a.set_region_accountid('southwest',4)
>>> a.set_region_accountid('southwest',5)
>>> b.set_region_accountid('northeast',1)
>>> b.set_region_accountid('northeast',2)
>>> b.set_region_accountid('northeast',3)
>>> b.set_region_accountid('southwest',4)
>>> b.set_region_accountid('southwest',5)
現在,讓我們嘗試比較兩個實例並生成遞歸異常:
>>> a == b
...
RuntimeError: maximum recursion depth exceeded while calling a Python object
您的對象不應返回哈希值,因為它是可變的。 如果將此對象放入字典或集合中,然后再進行更改,則可能永遠無法找到它。
為了使對象不可散列,您需要執行以下操作:
class MyClass(object):
__hash__ = None
這將確保該對象是不可散列的。
[in] >>> m = MyClass()
[in] >>> hash(m)
[out] >>> TypeError: unhashable type 'MyClass'
這回答了你的問題了嗎? 我懷疑不是因為您正在明確尋找哈希函數。
就您收到的RuntimeError而言,這是由於以下原因:
if self == other:
return True
這會使您陷入無限遞歸循環。 請嘗試以下操作:
if self is other:
return True
您不需要重寫__hash__
即可比較兩個對象(如果要自定義哈希, __hash__
,即在插入集合或字典時提高性能)。
另外,您在這里有無限遞歸:
def __eq__(self, other): if (other == self): return True if isinstance(other, RegionalCustomerCollection): return self.region_accountids == other.region_accountids return False
如果兩個對象都屬於RegionalCustomerCollection
類型,則由於==
調用__eq__
您將具有無限遞歸。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.