簡體   English   中英

覆蓋__eq__和__hash__以比較兩個實例的dict屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM