参考链接: Python使用散列的地址计算排序
Python用散列表来实现字典,散列表就是稀疏数组(数组中有空白元素),散列表中的元素叫做表元,字典的每个键值对都占用一个表元,一个表元分成两个部分,一个是对键的应用,另一个是对值的引用,因为表元的大小一致,所以可以通过稀疏数组(散列表)的偏移量读取指定的表元
Python会保证散列表中三分之一的表元都是空的,当向字典中添加元素时,散列表就会用键值对填充表元,当达到剩余三分之一表元是空的时,会将当前的散列表放到一个更大的空间中
当通过key获取字典的value时(求取dict[key]),过程如下:
1.调用hash(key)求取key的散列值。
2.把散列值的低几位当做偏移量,查找散列表里对应的表元。
3.如果表元为空,抛出异常(keyerror),如果表元不为空,会找到一对foundkey:foundvalue。
4.如果foundkey与key相等,返回foundvalue,如果foundkey与key不相等,发生散列冲突,执行第5步。
5.算法在散列值中再取几位,通过新的散列值计算索引,再查找对应的表元,然后执行3和4。
上述过程的流程图如下:
添加元素和更新值的过程和上述流程基本一致,添加元素时,如果发现是空表元,会直接添加值,更新值时,找到对应的表元后,原表元里的值会被更新为新值。
散列冲突并不会总发生,所以字典的速度很快。
因为字典通过key查找value是通过hash函数计算散列值,所以字典的key必须支持hash函数,且通过hash函数计算出的散列值是唯一的,所以key可以使用字符串(str),整型(int),元祖(tuple),但是不能是list
因为散列表是稀疏的,所以字典所占内存极高,典型的空间换时间
因为当向字典中添加键值对时,可能会发生散列冲突,导致键值对的出现在字典中的顺序不同,比如,添加一个key和value,如果没有发生散列冲突,那么该键值对出现在字典中的位置可能靠前,如果发生了散列冲突,就有可能出现在字典中靠后的位置,所以键值对在字典中的位置完全取决于添加顺序
举例
l=[(2,'two'), (1,'one'), (4,'four'), (3,'three')]
d1=dict(l);
print(d1.keys(), d1.items())
d2=dict(sorted(l));#按照key排序
print(d2.keys(),d2.items())
d3=dict(sorted(l, key =lambda x : x[1]))#按照value排序
print(d3.keys(),d3.items())
print(d1==d2==d3)
可见,虽然Python都认为上述三个字典是相等的,但是键值对在字典中的顺序完全不同
因为向字典中添加新的键值对时,有可能导致字典内部的散列表重新分配内存,当把字典中的元素重新添加到新的内存中时,可能导致散列冲突,从而导致键值对在字典中的位置发生变化
这样在循环迭代并同时添加键值对时就有可能跳过一些键
所以,在对已有字典进行循环迭代时,不要同时进行添加操作,而应该先新建一个空字典,将要添加的键值对放在空字典中,然后对原有字典和新字典进行合并
合并字典可用update方法
l1=[(2,'two'), (1,'one'), (4,'four'), (3,'three')]
l2=[(5,'five'), (6,'six'), (7,'seven'), (8,'eight')]
dl1=dict(l1)
dl2=dict(l2)
d=dict()
d.update(dl1)
d.update(dl2)
print(d)
编码就是将文本字符串转化为字节序列,解码就是将字节序列转化为文本字符串,常见的编解码格式有utf8,字节序列计算机识别,文本字符串人类识别
举例
s1='helloworld'
t1=s1.encode('utf8')
print(t1)
s2=t1.decode('utf8')
print(s2)
参考
1.《流畅的Python》
2. https://blog.csdn.net/jerry_1126/article/details/73017270
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出