python的可哈希和不可哈希

哈希函数

先来看一下官方文档上面对hashable的说明:

如果一个对象在其生命周期内有一个固定不变的哈希值 (这需要__hash__()方法) 且可以与其他对象进行比较操作 (这需要__eq__()方法) ,那么这个对象就是可哈希对象 (hashable) 。可哈希对象必须有相同的哈希值才算作相等。

由于字典 (dict) 的键 (key) 和集合 (set) 内部使用到了哈希值,所以只有可哈希 (hashable) 对象才能被用作字典的键和集合的元素。
所有python内置的不可变对象都是可哈希的,同时,可变容器 (比如:列表 (list) 或者字典 (dict) ) 都是不可哈希的。用户自定义的类的实例默认情况下都是可哈希的;它们跟其它对象都不相等 (除了它们自己) ,它们的哈希值来自id()方法。

字典的键

字典的键和集合都只能存放可哈希对象,当我们用不可哈希对象如list运行时会报错如下

TypeError: unhashable type: ‘list’

字典是根据键的哈希值查找对应值的,通过以下代码,可以看到元组是根据内容而不是id产生哈希值的

>>> a = (1,2)
... b = tuple([1,2])
... print(id(a))
... print(id(b))
... print(b)
... c = {a:1}
... print(c[b])
2477604860032
2477611649792
(1, 2)

集合的对象

当使用set()函数将不可哈希对象转换为集合时,同样会报错,如下

>>> a = [1,[2]]
... b = set(a)
... print(b)
Traceback (most recent call last):
  File "<input>", line 2, in <module>
TypeError: unhashable type: 'list'

自定义对象的哈希值

自定义对象默认是可哈希的,且根据对象的id产生哈希值,如下

>>> class Dog(object):
...     def __init__(self,name):
...         self.name = name
... dog1 = Dog("agou")
... print(dog1)
... dog2 = Dog("agou")
... print(dog2)
... print(Dog("agou"))
... a = {dog1:2}
... print(a[dog1])
... print(a[dog2])
<__main__.Dog object at 0x00000240DD18D610>
<__main__.Dog object at 0x00000240DD2C5160>
<__main__.Dog object at 0x00000240DD18DFA0>
2
Traceback (most recent call last):
  File "<input>", line 11, in <module>
KeyError: <__main__.Dog object at 0x00000240DD2C5160>

整型、浮点型、字符串的哈希值

对整型、浮点型、字符串分别求哈希值,结果如下

>>> print(hash(1));print(hash(0.5));print(hash('xyz'))
1
1152921504606846976
7472338868594177729
>>> print(hash(1));print(hash(0.5));print(hash('xyz'))
1
1152921504606846976
7472338868594177729
print(hash(1));print(hash(0.5));print(hash('xyz')) # pycharm下
1
1152921504606846976
6139473104200715737

可以看出整型的哈希值是固定的,浮点型的哈希值是一串整数且不见变化,字符串的哈希值是一串整数且在pycharm下每次运行会变化。

Python中可哈希和不可变

python中的不可变(immutable)对象都是可哈希(hashable)对象,用户自定义实例对象也默认可哈希,用户自定义实例对象的哈希值根据其id产生,故可变对象也可能可哈希。

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值