Python学习,不知道dict和set的效率有多高?先看文章

dict和set的背后
  • 为什么它们是无序的?
  • 为什么并不是所有的Python对象都可以当作dict的键或set里的元素?
  • 为什么dict的键和set的元素的顺序是根据它们被添加的次序而定的,以及为什么在映射对象的生命周期中,这个顺序并不是一成不变的?
  • 为什么不应该在迭代循环dict或是set的同时往里添加元素?

Python里的dict和set的效率有多高?

由实验得知,不管查询有多少个元素的字典或集合,所耗费的时间都能忽略不计(前提是字典或者集合不超过内存大小).

字典中的散列表

散列表其实是一个稀疏数组(总是有空白元素的数组被称为稀疏数组).在一般的数据结构教材中,散列表里的单元通常叫作表元(bucket).

在dict的散列表当中,每个键值对都占用一个表元,每个表元都有两个部分,一个是对键的引用,另一个是对值的引用.

因为所有的表元的大小一致,所以可以通过偏移量来读取某个表元.

Python会设法保证大概还有三分之一的表元是空的,所以在快要达到这个阈值的时候,原有散列表会被复制到一个更大的空间里面.

如果要把一个对象放入散列表,那么首先要计算这个元素键的散列值.Python中可以用hash()方法来做这件事情.

1.散列值和相等性

内置的hash()方法可以用于所有的内置类型对象.如果是自定义对象调用hash()的话,实际上运行的是自定义的__hash__.

如果这两个对象在比较的时候是相等的,那么它们的散列值必须相等,否则散列表就不能正常运行了.

例如,如果1==1.0为真,那么hash(1)==hash(1.0)也必须为真,但其实这两个数字(整型和浮点)的内部结构是完全不一样的.

既然提到了整型,CPython的实现细节里有一条是:如果有一个整型对象,而且它能被存进一个机器字中,那么它的散列值就是它本身的值.

为了让散列值能够胜任散列表索引这一角色,它们必须在索引空间中尽量分散开来.这意味着在最理想的状况下,越是相似但不相等的对象,它们散列值的差别应该越大.

import sys

# 通过sys.maxsize获取操作系统的整数最大值,转换成二进制,计算位数,加上一个符号位
MAX_BITS = len(format(sys.maxsize, 'b'))
print('%s-bit Python build' % (MAX_BITS + 1))


def hash_diff(o1, o2):
    h1 = '{:>0{}b}'.format(hash(o1), MAX_BITS)  # 计算o1的散列值,并用0补满空位
    h2 = '{:>0{}b}'.format(hash(o2), MAX_BITS)  # 计算o2的散列值,并用0补满空位
    # 比较h1和h2的每一位,用!标识出来,否则用' '表示
    diff = ''.join('!' if b1 != b2 else ' ' for b1, b2 in zip(h1, h2))
    count = '!={}'.format(diff.count('!'))  # 显示不同的总数
    width = max(len(repr(o1)), len(repr(o2))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值