前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >id,hash 和 hashlib

id,hash 和 hashlib

作者头像
不可言诉的深渊
发布2019-07-27 19:52:47
1.2K0
发布2019-07-27 19:52:47
举报

看了标题,大家应该知道今天我要讲的内容了,其中 id 和 hash 是内置的两个函数,hashlib 是一个模块,它们的共同点就是给每一个对象一个特定的标志,当然它们也有不同之处。

id

id 函数有一个参数,参数类型没有限制,可以是任意类型(实际上是 object 类型),返回一个对象的身份。这个函数确保参数在同时存在的对象中独一无二,如果是 CPython(底层语言是 C),该函数返回该对象的内存地址。其实 Python 有很多,远远不止一个 CPython,还有 Jython(底层语言是 Java) 和IronPython(底层语言是 C#)等。如果不是 CPython 这个 id 的返回值有什么规律我就不做演示了,大家可以自己尝试,下面我就来演示一下在 CPython 中为什么返回的是内存地址。

首先定义一个列表 a,然后把 a 赋值给 b,此时 b 和 a 应该值相等,如果地址相等的话,那么我修改 b 时,a 也会跟着变化,通过下面的操作,我们可以发现地址是相等的,id(a) 和 id(b) 相等,而且值是一个整数,接下来我们只要做一件事就可以确定这是通过一个算法生成的特定值还是内存中的地址(会变化),其实很简单,我们重新打开一个解释器继续创建同样的对象并且用 id 得到值,如图所示。

很明显,不同的解释器值不一样,所以它返回的是内存地址,而不是由一种算法产生的一个特定的值。

hash

hash 函数有一个参数,参数类型有一点限制,必须是可哈希的类型,返回传入对象的哈希值,两个相等的对象也必然有相等的哈希值。

可哈希类型主要是不可变类型,当然自己定义的类默认也是可哈希的,怎么样自己可以定义不可哈希的类型呢?其实很简单,继承不可哈希的类就完事了。如果我不继承,就想自己手写一个不可哈希的类该怎么办?其实很简单,重写 __eq__ 魔法方法的同时,不去重写 __hash__ 方法,那么这个类就不可哈希。下面我就不做验证了,直接演示一下为什么两个相等对象有着相等的 hash 值。

首先定义字符串 a,然后定义字符串 b,a == b,hash(a) == hash(b),证明完毕。我们发现 hash(a) 返回一个整数,接下来我们证明新开一个解释器,用同样的值再来定义一个字符串 a,看看 hash(a) 是不是还是这个值,如图所示。

这就怪了,按理来说如果值相等 hash 应该也相等才对啊,其实这个说法只能适用于一个解释器,多个解释器这样的说法就行不通了,如果要想在多个解释器保证这种说法正确就不能使用此函数,应该使用 hashlib 模块的函数。下面我们只要验证同一个解释器的两个值相等的对象有不同的地址就行了。

可以发现地址不相等但值相等就有相同的哈希值。

hashlib

为了解决 hash 函数带来的问题,就必须使用模块 hashlib 了,hashlib 提供了很多 hash 算法,其中常用的也就两个——md5 和 sha1,两个算法原理差不多,都是对称加密。这里就以 sha1 为例讲一下。

sha1 函数最多有一个参数,如果有 1 个参数,参数类型必须是字节类型。该函数返回一个 sha1 的哈希对象,如果要获取哈希后的字符串,就还要调用该对象的 hexdigest 方法。下面我就来证明即使解释器不同,只要值相等就会得到相等的哈希后的字符串。

可以发现不同的解释器也可以获得相同的哈希值。

经过上面实验可以得出以下结论,如果要想获得用户输入的哈希值最好使用 hashlib 模块中的函数,因为你服务器的解释器和用户客户端的解释器(假设用户的客户端是 Python 实现的)不是一个解释器,内置的 hash 函数会带来一些问题。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python机器学习算法说书人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档