开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情
深入python的dict和set
一,dict的abc继承关系
dict 的抽象基类是
Mapping
from collections import Mapping
d = {}
print(isinstance(d, Mapping))
二,dict的常用方法
...自己脑补
三,dict的子类
不要去继承 dict 和 set ,他们内部是用c语言写的,使用父类的方法有时不会被调用
如果要继承,使用 collections.UserDict,这个用 python 重写过字典的,继承之后调用父类的方法没有问题
四,set和frozenset
set 可变集合,fronzenset(不可变集合)
-
set 可变集合
# 无序并且不重复,不能修改里面的值 s = set('abdefgabcdefg') print(s) -
fronzenset 不可变集合,可以作为字典的 key
s = frozenset('abcdefgabcdefg') print(s)
五,dict和set的实现原理
dict 和 list 对比
- dict 的性能远远大于 list
- 在 list 中,查找元素是随着数据的翻倍成倍增加
- 在 dict 中查找元素,不会随着 dict 的增大而增大
-
实现原理
-
在python的dict中间进行查找某个key操作时,查找所需时间不会随着dict中键值对数量增多而变长,(时间复杂度为O(1))但是list中就会(时间复杂度为O(N)),这是因为list查询实现的方式是循环遍历所有列表,然后查找对应的元素,所以列表中元素越多,查找越费时间,但是同一个dict中的所有key的id在内存中是连续的,并且其数据的存储方式为hash表的形式,原理图如下
-
dict中的key会调用内置的hash()方法(如果是自定义的类就会调用自定义的hash;),把hash()得到的新key作为 索引或者说数组下标,找到位置把key和value的引用一起存入数组中
因为本质上是数组,所以通过偏移量就能查找到对应的目标
因此:
-
dict的key 或者 set的值都必须是可hash的不可变对象,都是可hash的,str,fronzenset, tuple, 自己实现的类(带有__ hash __魔法函数)
-
dict 的内存花销大(hash简单的来说即映射,映射之后,不可能是连续的存在内存空间中的,总有一些内存时空的,当发现内存空间中的“空”只有1/3时,便会触发扩容操作,以免引起hash冲突),但是查询速度快。自定义的对象,或者python内部的对象都是dict包装的。
-
dict的存储顺序和元素的添加顺序有关
-
添加的数据有可能改变已有的数据顺序(扩容时,需要将原来的dict,复制移动到新的内存空间,此时将“挤出”已有的“空”,所以每个key的偏移可能改变)