2

在 Python3 中,任何类都有一个默认值__hash__,它根据成员变量计算哈希值。我可以将它(显式或隐式)设置为 None 以使该类不可散列,这当然有一些用例。

但是有理由覆盖__hash__吗?

我找不到一个。

4

1 回答 1

3

是的!任何时候你覆盖__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)

现在,当您将其用作键时,它的行为就像您期望任何其他此类对象的行为一样。

于 2019-06-25T06:31:33.907 回答