我在__eq__
,__hash__
及其关系中看到过很多问题,即使我遇到了一些我想澄清的令人惊讶的现象。
我有一个字典team
,其中包含许多player
个实例作为其键。类player
本身相当复合,但包括__hash__
和__eq__
。我可能还会注意到player
包含字典属性,我认为这是导致问题的原因。
无论如何,我的代码如下:
if player in team.keys():
name, height = team[player]
奇怪的现象是,当player in team
返回True
时(因此条件得到满足并且下线被执行),第二行引发KeyError
。我无法弄清in
如何正常工作,而键没有正确散列。
有什么建议吗?
player
类包含以下魔术方法。 cnfg_dict
是一个包含多个用户指定配置的字典,required_attrs
用于区分player
个实例(据称......)。
def __init__(self, cnfg_dict):
self.config_dict = cnfg_dict
self.required_attrs = ['attr1', 'attr2']
def __eq__(self, other):
return all([self.config_dict[attr] == other.config_dict[attr] for attr in self.required_attrs])
def __ne__(self, other):
required_attrs = ['dt', 'author']
return any([self.config_dict[attr] != other.config_dict[attr] for attr in required_attrs])
def __repr__(self):
return str([str(a)+'='+str(self.config_dict[a]) for a in self.required_attrs])
def __hash__(self):
return hash(repr(self))
答案 0 :(得分:0)
我不满意你的大赌注,彼此相等的物体将具有相同的 repr 功能。当然,如果你正在处理数字,这是一个风险。这是一个例子:
[in] >>> a = {'name': 'Zelaznik', 'height': 6}
[in] >>> b = {'name': 'Zelaznik', 'height': 6.0}
[in] >>> a == b
[out] >>> True
[in] >>> repr(a['height']) == repr(b['height'])
[out] >>> False
我打赌你在玩家的身高时遇到了这个问题。
这是解决哈希功能的快捷方法:
def __hash__(self):
dct = self.confg_dict
keys = self.required_attr
return hash(tuple([dct[k] for k in keys]))
看起来你正在处理一个班级"播放器"它有一组预定的键,在这种情况下,你可以通过使用一个命名元组让自己更轻松。
from collections import namedtuple
Player = namedtuple('Player', ('name', 'height', 'opt_attr1', 'opt_attr2'))
Player.__new__.__defaults__ = (None, None) #Sets default values for last two arguments.
https://docs.python.org/2/library/collections.html#collections.namedtuple