【发布时间】:2016-11-25 21:48:58
【问题描述】:
我最近在 Python 中尝试了以下命令:
>>> {lambda x: 1: 'a'}
{<function __main__.<lambda>>: 'a'}
>>> def p(x): return 1
>>> {p: 'a'}
{<function __main__.p>: 'a'}
dict 的成功创建表明 lambda 和常规函数都是可散列的。 ({[]: 'a'} 之类的失败,TypeError: unhashable type: 'list')。
哈希显然不一定是函数的ID:
>>> m = lambda x: 1
>>> id(m)
140643045241584
>>> hash(m)
8790190327599
>>> m.__hash__()
8790190327599
最后一条命令显示__hash__ 方法是为lambdas 显式定义的,也就是说,这不是 Python 根据类型计算的自动魔法。
使函数可散列化的动机是什么?另外,函数的哈希值是多少?
【问题讨论】:
-
我真的觉得这是你在对“你为什么不呢?”有一个好的答案之前不应该考虑的问题。
-
@Hurkyl。因为它需要为一件事增加额外的维护负担。有人必须设计和编写
__hash__函数,所以他们清楚地看到了它的好处。我想知道是什么让他们不只是不管它。 -
虽然给出了答案,但似乎禁用散列函数需要更多的工作,而不仅仅是从对象继承它。所以事实上,其中一个考虑因素可能是减少维护债务。
-
@MadPhysicist,无论哪种方式,代码都很简单。在
C中,对象的类型由struct PyTypeObject表示,该结构的tp_hash成员定义__hash__()发生的情况。如果该成员初始化为 0,则它继承__hash__()。如果您希望该类型拒绝散列,只需将其初始化为PyObject_HashNotImplemented即可。 (而且如果类型要实现自定义散列,你插入类型的自定义散列函数的地址。)所以维护负担真的与它无关。