文章目录
字典
字典的特点
无序、可变、键值对
每个元素是一个键值对,包含键对象和值对象
键对象不可以重复(字典是一个依靠键对象的散列值来排列元素的散列表,键对象的散列值不可以重复)
创建方式
a = {'name':'marx','age':18,'salary':'unknown'}
a = dict('name'='marx','age'=18)
,键值对的元组
a = dict[('name','marx'),('age',18)]
,键值对元组组成的列表
a = dict(zip(键列表,值列表))
,zip()方式也同样适用于元组
a = dict.formkeys(['name','age'])
,创建值对象为空的字典,注意其中键对象是以列表形式出现,而不是只用逗号隔开
字典元素的访问
a['name']
,类似列表和元组中用a[0]
的访问方式
a.keys()
,列出字典a中所有的键对象
a.items()
,列出字典a中所有的键值对
a.values()
,列出字典a中所有的值对象
a.get('name')
,获取字典a中’name’键对象的值对象
len(a)
,获取字典a的键值对个数
'name' in a
,not in
,判断键对象是否在字典a中
字典元素的添加
a['address'] = '南天门'
,如果字典a中没有address这个键,就添加这个键值对;如果有,就更新值对象
a.update(b)
,b是一个新的字典,将b字典中的内容拷贝到字典a中,重复键就覆盖,没有的键就新增
字典元素的删除
del(a['name'])
,删除字典a中键对象为name的键值对
a.clear()
,清空字典a,字典a变成空字典
a.pop('name')
,返回值是name的值对象,抛出name后字典a中就没有这个键值对了
a.popitem('name')
,乱序抛出字典a中的键值对,当a为空字典时会抛异常
字典的序列解包
序列解包用于列表
[a,b,c]=[10,20,30]
❓ 去掉方括号好像没有影响
序列解包用于元组
x,y,z = (10,20,30)
(x,y,z) = (10,20,30)
❓ 不太理解列表和元组的序列解包的区别,看起来都是一次性对三个变量赋值
序列解包用于字典
序列解包用于字典默认是对键对象进行操作
a = {'name':'gaoqi','age':18,'job':'programmer'}
m,n,l = a
序列解包对字典中的值对象进行操作
e,f,g = a.values()
序列解包对字典中的键值对进行操作
e,f,g = a.items()
表格的构建和打印,列表和字典综合嵌套
思路:
- 构造表格
- 用字典构建每一行,需要储存数据
- 用列表装起来每一行,需要按重复格式增殖
- 打印
- 循环的是行数,也就是列表的元素数
- 按字典键对象打印值对象
r1 = {"name":"高小一", "age":18, "salary":30000, "city":"北京"}
r2 = {"name":"高小二", "age":19, "salary":20000, "city":"上海"}
r3 = {"name":"高小五", "age":20, "salary":10000, "city":"深圳"}
tb = [r1,r2,r3]
#获得第二行的人的薪资
print(tb[1].get('salary'))
#打印所有人的薪资
for i in range(len(tb)):
print(tb[i].get('salary'))
#打印所有数据
for i in range(len(tb)):
print(tb[i].get('name'),tb[i].get('salary'),tb[i].get('city'))
字典核心底层原理
字典的本质是一个散列表,即稀疏数组,即总是有空白元素的数组
散列表中的每个单元叫bucket(表元、桶)
每个bucket有两个部分:键对象的引用、值对象的引用
所有bucket的结构、大小都一样,通过偏移量来读取指定的bucket
字典的键对象:必须可散列,即可以转换出哈希值,字符串、数字、元组皆可
把键对象放入字典的底层过程
- 计算键对象的散列值
bin(hash('name')
- 数组长度假设为8,也就是最小的索引值是7,是最大的3位二进制数,
- 取name的散列值最右端的3位,转换为0-7的索引值,假设为6
- 索引值为6的bucket是否为空
- 为空,将name键对象放入该bucket
- 不为空,取name散列值从最右端往左移动3位后的3位数,转换为0-7的索引值…重复步骤2,直到找到空bucket
根据键查找键值对的底层过程
跟上面这个差不多
- 算出键对象的散列值x
- 从散列值最右取值,转换成序号,找bucket的索引值
- 看bucket是否为空
- 为空,返回None
- 不为空,
- 取出该bucket中的键对象,算出该键对象的散列值y
- 对比x与y是否相等
- 相等,返回该bucket对应的值对象
- 不相等,回到步骤2,往左移动3位再找bucket
字典底层原理小结
- 键对象必须是可以散列的
- 数字、字符串、元组
- 自定义对象满足以下条件
- 支持
hash()
函数 - 支持通过
__eq__()
方法检验相等性 - 若 a==b为真,则hash(a)==hash(b)也为真
- 支持
- 键查询很快
- 字典是以空间换时间
- 字典中添加新建可能会导致扩容,导致散列表中键的次序改变,因此不要在遍历字典的同时对字典进行修改
集合
集合的特点
集合的底层就是字典,但只有字典的键对象
集合是无序的、可变的、元素不能重复的(跟字典几乎一样)
集合的创建
a = {'a','b','age'}
a = set(b)
,将可迭代对象b转换为集合,如果有重复元素就会只留下一个
集合的删除
a.clear()
,清空后得到一个空集合a
a.remove(10)
,删除集合a中的指定元素10
集合的其它操作
就像数学中的集合,并集、交集、差集
并集:a|b
, a.union(b)
差集:a-b
, a.difference(b)
交集:a&b
, a.intersecion(b)