为什么以及如何 Python 函数是可散列的? [英] Why and how are Python functions hashable?
问题描述
我最近在 Python 中尝试了以下命令:
<预><代码>>>>{lambda x: 1: 'a'}{<function __main__.<lambda>>: 'a'}>>>def p(x): 返回 1>>>{p:'a'}{<function __main__.p>: 'a'}dict
创建的成功表明 lambda 和常规函数都是可散列的.(类似于 {[]: 'a'}
失败,TypeError: unhashable type: 'list'
).
哈希显然不一定是函数的 ID:
<预><代码>>>>m = λ x: 1>>>身份证(米)140643045241584>>>哈希(米)8790190327599>>>m.__hash__()8790190327599最后一个命令显示 __hash__
方法是为 lambda
显式定义的,也就是说,这不是 Python 基于类型计算的一些自动魔法.
使函数可哈希化的动机是什么?作为奖励,函数的哈希值是多少?
没什么特别的.如果您检查函数类型的未绑定 __hash__
方法,您会看到:
'object'对象的部分意味着它只是从
object
继承了默认的基于身份的__hash__
.函数 ==
和 hash
通过标识工作.id
和 hash
之间的区别对于任何继承 object.__hash__
的类型都是正常的:
<小时>
您可能认为 __hash__
应该只为不可变对象定义,而且您几乎是对的,但这缺少一个关键细节.__hash__
应该只为 ==
比较中涉及的所有内容 不可变的对象定义.对于 ==
基于身份的对象,基于身份的 hash
也是完全标准的,因为即使对象是可变的,它们也不可能是可变的以某种方式改变他们的身份.文件、模块和其他具有基于身份的 ==
的可变对象都以这种方式运行.
I recently tried the following commands in Python:
>>> {lambda x: 1: 'a'}
{<function __main__.<lambda>>: 'a'}
>>> def p(x): return 1
>>> {p: 'a'}
{<function __main__.p>: 'a'}
The success of both dict
creations indicates that both lambda and regular functions are hashable. (Something like {[]: 'a'}
fails with TypeError: unhashable type: 'list'
).
The hash is apparently not necessarily the ID of the function:
>>> m = lambda x: 1
>>> id(m)
140643045241584
>>> hash(m)
8790190327599
>>> m.__hash__()
8790190327599
The last command shows that the __hash__
method is explicitly defined for lambda
s, i.e., this is not some automagical thing Python computes based on the type.
What is the motivation behind making functions hashable? For a bonus, what is the hash of a function?
It's nothing special. As you can see if you examine the unbound __hash__
method of the function type:
>>> def f(): pass
...
>>> type(f).__hash__
<slot wrapper '__hash__' of 'object' objects>
the of 'object' objects
part means it just inherits the default identity-based __hash__
from object
. Function ==
and hash
work by identity. The difference between id
and hash
is normal for any type that inherits object.__hash__
:
>>> x = object()
>>> id(x)
40145072L
>>> hash(x)
2509067
You might think __hash__
is only supposed to be defined for immutable objects, and you'd be almost right, but that's missing a key detail. __hash__
should only be defined for objects where everything involved in ==
comparisons is immutable. For objects whose ==
is based on identity, it's completely standard to base hash
on identity as well, since even if the objects are mutable, they can't possibly be mutable in a way that would change their identity. Files, modules, and other mutable objects with identity-based ==
all behave this way.
这篇关于为什么以及如何 Python 函数是可散列的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!