【问题标题】:__hash__, __eq__ and "in" operator__hash__、__eq__ 和“in”运算符
【发布时间】:2014-06-11 18:20:09
【问题描述】:

我已经看到很多关于__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))

【问题讨论】:

  • 你没有使用player in team;你正在使用player in team.keys();这仅测试列表中的相等性(至少在 Python 2 中)。这确实表明您的对象具有不正确的__hash__ 实现(相等的对象必须具有相等的__hash__ 值)。
  • 您能否向我们展示您的__hash____eq__ 实现?或者,至少是您问题的可重现简化版本。

标签: python hash


【解决方案1】:

我不喜欢你打赌彼此相等的对象将具有相同的 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

我敢打赌,你在球员身高方面遇到了这个问题。

下面是解决 hash 函数的快速方法:

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

【讨论】:

    猜你喜欢
    • 2017-03-14
    • 2017-12-23
    • 2018-09-13
    • 2020-08-28
    • 2011-03-28
    • 2011-03-05
    • 2015-08-01
    • 2016-11-01
    • 1970-01-01
    相关资源
    最近更新 更多