首页 > 解决方案 > 当 __hash__ 和 __eq__ 在没有参数的情况下不可调用时,Python 的 dict 如何将类型管理为键?

问题描述

Python 文档指出 dict 键必须是可散列的,这意味着具有__hash____eq__

我试图了解在 dict 中使用类型作为键是如何工作的,至少在默认情况下,这两种方法都需要一个实例作为第一个参数。

考虑下面的代码及其输出:

class Apple:
    pass

class Orange:
    pass

lookup = {Apple: lambda: print('Apple!'), Orange: lambda: print('Orange!')}

try:
    print(Apple.__hash__())
except Exception as e:
    print(e)
    
try:
    print(Apple.__eq__())
except Exception as e:
    print(e)

an_apple = Apple()
an_orange = Orange()

lookup[type(an_apple)]()
lookup[type(an_orange)]()
descriptor '__hash__' of 'object' object needs an argument
descriptor '__eq__' of 'object' object needs an argument
Apple!
Orange!

dict 如何获取哈希和检查类型的相等性?

标签: python

解决方案


Python 不会在实例上查找魔术方法。它在班级本身上查找它们。在你的情况下,是。Appletype

>>> class Apple: pass
... 
>>> hash(Apple)
5929200437980
>>> type.__hash__(Apple)
5929200437980

同样的事情发生在__eq__. 如果您尝试将魔术方法附加到实例而不是类,也可以看到这一点。

>>> class Apple:
...   def __hash__(self):
...     return 1
... 
>>> my_apple = Apple()
>>> my_apple.__hash__ = lambda: 2
>>> hash(my_apple) # 1, not 2
1
>>> my_apple.__hash__()
2
>>> Apple.__hash__(my_apple)
1

请注意,Apple两者my_apple__hash__定义了它们,但调用的是类的方法,而不是实例上的方法。


推荐阅读