__hash __,__ eq__和" in"操作者

时间:2014-06-11 18:20:09

标签: python hash

我在__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))

1 个答案:

答案 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