为什么以及如何 Python 函数是可散列的? [英] Why and how are Python functions hashable?

查看:34
本文介绍了为什么以及如何 Python 函数是可散列的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在 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__ 方法,您会看到:

<预><代码>>>>def f(): 通过...>>>类型(f).__hash__<'object'对象的槽包装器'__hash__'>

'object'对象的部分意味着它只是从object继承了默认的基于身份的__hash__.函数 ==hash 通过标识工作.idhash 之间的区别对于任何继承 object.__hash__ 的类型都是正常的:

<预><代码>>>>x = 对象()>>>编号(x)40145072L>>>哈希(x)2509067

<小时>

您可能认为 __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 lambdas, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆