我正在努力理解如何根据每个实例拥有的基础dict属性正确比较对象。
由于我要覆盖__eq__
,我还需要覆盖__hash__
吗?我没有牢牢掌握何时/何地这样做,并且可以真正使用一些帮助。
我在下面创建了一个简单的示例来说明我遇到的最大递归异常。 RegionalCustomerCollection
按地理区域组织帐户ID。如果区域及其各自的RegionalCustomerCollection
是accountid
,则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
现在让我们尝试比较两个实例并生成递归异常:
{{1}}
答案 0 :(得分:3)
您的对象不应该返回哈希值,因为它是可变的。如果将此对象放入字典或设置中,然后再将其更改,则可能永远无法再找到它。
为了使对象不可删除,您需要执行以下操作:
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
答案 1 :(得分:1)
您不需要覆盖__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__
以来,您将无限递归。