字典
介绍
字典是“键值对”的无序可变序列,字典中的每个元素都是一个“键值对”,包含:“键对象”和“值对象”。
可以通过“键对象”实现快速获取、删除、更新对应的“值对象”
字典特点:
无序, 可变, 大括号 {} + 键值对 k,v
字典是 Python 项目中最常用的序列类型之一, 对应Java 中常用的 Json 数据类型
操作
字典的创建
通过 {} + kv
来创建
通过dict()来创建字典对象(两种方式)
过zip()创建字典对象
通过fromkeys创建值为空的字典
字典(类比Json)
“键”是任意的不可变数据,比如:整数、浮点数、字符串、元组. 但是:列表、字典、集合这些可变对象,不能作为“键”.
并且“键”不可重复。
#“值”可以是任意的数据,并且可重复
a = {'name': 'TimePause',
'age': 18, 'sex': 'man'}
print(a)
b =
dict(name='TimePause', age=18, sex='man')
a = dict([("name", "TimePause"),
("age", 18)])
print(b)
print(a)
c = {} # 空的字典对象
d = dict() #
空的字典对象
print(c)
print(d)
k = ["name", "age",
"sex"]
v = ["TimePause", 18, "man"]
d = dict(zip(k, v))
print(d) #
{'name': 'TimePause', 'age': 18, 'sex': 'man'}
f =
dict.fromkeys(["name", "age", "sex"])
print(f) # {'name': None, 'age': None,
'sex': None}
元素的访问:
字典元素的访问
a = {'name': 'TimePause', 'age': 18, 'sex': 'man'}
[键] 获得“值”。若键不存在,则抛出异常。
b = a["name"]
print(b)
#c = a["birthday"]
KeyError: 'birthday'
#print(c)
优点是:指定键不存在,返回None;也可以设定指定键不存在时默认返回的对象. 推荐使用get()获取“值对象”
b =
a.get("name")
c = a.get("birthday")
d = a.get("birthday",
"值不存在")
print(b)
print(c)
print(d)
b =
a.items()
print(b) # dict_items([('name', 'TimePause'), ('age', 18), ('sex',
'man')])
k = a.keys()
v = a.values()
print(k, v)
len() 键值对的个数
b = len(a)
print(b)
print("name"
in a) # True
字典元素添加、修改、删除
a =
{'name': 'TimePause', 'age': 18, 'sex': 'man'}
a['name'] =
"时间静止"
a['phone'] = 18322222222
print(a)
将新字典中所有键值对全部添加到旧字典对象上。如果 key 有重复,则直接覆盖
a = {'name': 'TimePause', 'age': 18,
'sex': 'man'}
b = {'name': '时间静止', 'age': 18, 'phone':
18322222222}
a.update(b) # 旧字典.update(新字典)
print(a)
del() 方法;或者 clear() 删除所有键值对; pop() 删除指定键值对,并返回对应的“值对象
a = {'name':
'TimePause', 'age': 18, 'sex': 'man'}
del (a["name"])
print(a) # {'age':
18, 'sex': 'man'}
a.pop("age")
print(a) # {'sex': 'man'}
popitem() :以后入先出的方式删除和返回该键值对
#删除并返回一个(键,值)对作为 2 元组。对以 LIFO(后进先出)顺序返回。如果 dict
为空,则引发 KeyError。
a = {'name': 'TimePause', 'age': 18, 'sex':
'man'}
a.popitem()
print("第一次调用popitem",
a)
a.popitem()
print("第二次调用popitem",
a)
a.popitem()
print("第三次调用popitem", a)
#a.popitem() # KeyError:
'popitem(): dictionary is empty'
#print("第四次调用popitem", a)
序列解包
序列解包可以用于元组、列表、字典。序列解包可以让我们方便的对多个变量赋值
#序列解包
#序列解包可以用于元组、列表、字典。序列解包可以让我们方便的对多个变量赋值
x, y, z = (20, 30, 10) #
变量
(a, b, c) = (9, 8, 10) # 元组
[m, n, p] = [10, 20, 30] # 列表
序列解包用于字典时,默认是对“键”进行操作;
a = {'name': 'TimePause', 'age': 18, 'sex':
'man'}
name, age, sex = a
print(name)
如果需要对键值对操作,则需要使用items()
name, age, sex = a.items()
print(name)
如果需要对“键”进行操作,则需要使用keys()
name, age, sex = a.keys()
print(name)
如果需要对“值”进行操作,则需要使用values()
name, age, sex = a.values()
print(name)
18
表格数据使用字典和列表存储访问
#表格数据使用字典和列表存储访问
#定义字典对象
a1 = {"name": "才子队", "season": 1, "winner":
"比尔"}
a2 = {"name": "九头蛇队", "season": 2, "winner": "皮尔斯"}
a3 = {"name":
"巨亨队", "season": 3, "winner": "卡罗尔"}
#定义列表对象tl
tl = [a1, a2,
a3]
print(tl)
print(tl[1].get("name"))
#输出所有获胜人员名称
for x in
range(3):
print(tl[x].get("winner"))
#打印表的所有数据
for i in
range(len(tl)):
print(tl[i].get("name"), tl[i].get("season"),
tl[i].get("winner"))
字典核心底层原理(重要)
一
: 将一个键值对放进字典的底层过程
字典对象的核心是散列表. 散列表是一个稀疏数组(总是有空白元素的数组)
数组的每个单元叫做 bucket. 每个 bucket
有两部分:一个是键对象的引用,一个是值对象的引用
由于所有 bucket 结构和大小一致,我们可以通过偏移量来读取指定bucket
下面操作将一个键值对放入字典
假设字典a对象创建完后,数组长度为8
a =
{}
a["name"]="比尔"
我们要把”name”=”比尔”这个键值对放到字典对象a中,
首先第一步需要计算键”name”的散列值。Python中可以通过hash()来计算。
下面我们通过
Python Console 来查看 name 的hash值
bin(hash("name"))
'-0b1010111101001110110101100100101'
由于数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即“101”,十进制是数字5。
我们查看偏移量6对应的bucket是否为空
如果为空,则将键值对放进去。如果不为空,则依次取右边3位作为偏移量,即“100”,十进制是数字4
再查看偏移量为7的bucket是否为空。直到找到为空的bucket将键值对放进去.
流程图如下:
字典扩容
python会根据散列表的拥挤程度扩容。“扩容”指的是:创造更大的数组,将原有内容拷贝到新数组中。
接近2/3时,数组就会扩容
二. 根据键查找“键值对”的底层过程
通过 Python console() 查看字典元素值如下
a.get("name")
'比尔'
1
2
当调用a.get(“name”),就是根据键“name”查找到“键值对”,从而找到值对象“比尔”。
我们仍然要首先计算“name”对象的散列值:
bin(hash("name"))
'-0b1010111101001110110101100100101'
1
2
和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。
假设数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即
101 ,十进制是数字5。
我们查看偏移量5,对应的 bucket 是否为空。如果为空,则返回 None 。
如果不为空,则将这个 bucket
的键对象计算对应散列值,和我们的散列值进行比较,
如果相等。则将对应“值对象”返回。
如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后,仍然没有找到。则返回None
。
流程图如下:
用法总结:
字典在内存中开销巨大 (空间换时间)
键查询速度很快
(通过位运算+Hash运算)
往字典里面添加新键值对可能导致扩容,导致散列表中键的次序变化。
因此,不要在遍历字典的同时进行字典的修改
键必须可散列
数字、字符串、元组,都是可散列的
如果是自定义对象,
需要支持下面三点:
(1) 支持 hash() 函数 (2) 支持通过 eq () 方法检测相等性 (3) 若 a==b 为真,则
hash(a)==hash(b) 也为真
全部0条评论
快来发表一下你的评论吧 !