在 Python3 中,任何类都有一个默认值__hash__
,它根据成员变量计算哈希值。我可以将它(显式或隐式)设置为 None 以使该类不可散列,这当然有一些用例。
但是有理由覆盖__hash__
吗?
我找不到一个。
在 Python3 中,任何类都有一个默认值__hash__
,它根据成员变量计算哈希值。我可以将它(显式或隐式)设置为 None 以使该类不可散列,这当然有一些用例。
但是有理由覆盖__hash__
吗?
我找不到一个。
是的!任何时候你覆盖__eq__
,并且还希望能够将对象用作集合或字典中的键。这在值类型或您的对象代表现实世界实体的情况下尤其常见。
__hash__
根本不散列成员变量。对于没有__hash__
或__eq__
未定义的对象,它会根据其内部指针返回一些值。如果__eq__
已定义,则调用该方法将导致 TypeError.work
考虑这个默认__eq__
和__hash__
行为不是很好的简单案例:
import getpass
class User:
def __init__(self, name):
self.name = name
def currentUser():
return User(getpass.getuser())
me = currentUser()
passwords = {}
passwords[me] = "sw0rdfish";
这有一些奇怪的行为:me == currentUser()
为假,并passwords[currentUser()]
抛出 KeyError。因此,为了尝试修复它,我们定义了一个__eq__
:
def __eq__(self, other):
return self.name == other.name
现在me == currentUser()
是真的,但尝试分配密码会抛出TypeError: unhashable type: 'User'
. 现在我们已经到了要覆盖的地步__hash__
:
def __hash__(self):
return hash(self.name)
现在,当您将其用作键时,它的行为就像您期望任何其他此类对象的行为一样。