一、字典 dict
字典是"键值对"的无序可变序列,字典中的每个元素都是一个"键值对",包含:"键对象"和"值对象"。可以通过"键对象"实现快速获取、删除、更新对应的"值对象"。
列表中我们通过"下标数字"找到对应的对象。字典中通过"键对象"找到对应的"值对象"。
"键"是任意的不可变数据,比如:整数、浮点数、字符串、元组。
但是:列表、字典、集合这些可变对象,不能作为"键"。
并且"键"不可重复。
"值"可以是任意的数据,并且可重复。
字典的核心底层原理
字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做
bucket
。每个bucket
有两部分:一个是键对象的引用,一个是值对象的引用。由于,所有
bucket
结构和大小一致,我们可以通过偏移量来读取指定bucket
。
假设字典a对象创建完后,数组长度为8:
由于数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即"101",十进制是数字5。我们查看偏移量5,对应的bucket是否为空。如果为空,则将键值对放进去。如果不为空,则依次取右边3位作为偏移量,即"100",十进制是数字4。再查看偏移量为4的bucket是否为空。直到找到为空的bucket将键值对放进去。流程图如下:
根据键查找"键值对"的底层过程和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。 假设数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即101,十进制是数字5。我们查看偏移量5,对应的bucket是否为空。如果为空,则返回None。如果不为空,则将这个bucket的键对象计算对应散列值,和我们的散列值进行比较,如果相等。则将对应"值对象"返回。如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后,仍然没有找到。则返回None。流程图如下:
用法总结:
字典在内存中开销巨大,典型的空间换时间。
键查询速度很快
往字典里面添加新键值对可能导致扩容,导致散列表中键的次序变化。因此,不要在遍历字典的同时进行字典的修改
键必须可散列
数字、字符串、元组,都是可散列的
自定义对象需要支持下面三点:(面向对象章节中再展开说)
支持
hash()
函数支持通过
__eq__()
方法检测相等性若
a==b
为真,则hash(a)==hash(b)
也为真
二、字典的创建
2.1、使用 {} 创建字典
python语言中字典是通过{}来进行描述的,所以创建字典的时候,直接可以使用 {}进行创建.
dct = {"key": value, "key1": value1}
ps: 多个键值对儿之间必须使用 ','隔开.
python
# 创建一个字典
dict1 = {
"name": "Alice",
"age": 30,
"city": "New York"
}
print(dict1)
# 输出: {'name': 'Alice', 'age': 30, 'city': 'New York'}
2.2、使用dict函数创建字典
简介:
python语言中可以直接使用 内置dict() 创建字典. 这类方法特别适用于 key 是字符串的情况.
使用方式:
dct = dict(key1=value1, key2=value2)
ps: 多个键值对儿之间使用 = 隔开
python
dict1 = dict(name="Bob", age=25, city="Los Angeles")
print(dict1)
# 输出: {'name': 'Bob', 'age': 25, 'city': 'Los Angeles'}
2.3、字典推导式
简介:
python语言提供了字典的推导式,可以直接推导出字典里面的值。
语法格式:
dict = {key:value for item in iterable}
python
# 使用字典推导式创建字典
keys = ['a', 'b', 'c']
values = [1, 2, 3]
dict4 = {keys[i]: values[i] for i in range(len(keys))}
print(dict4)
# 输出: {'a': 1, 'b': 2, 'c': 3}
2.4、通过zip()创建字典对象
zip函数:
zip函数可以将两个列表合并成一个字典,列表中的元素分别对应字典的key:value
使用方式:
zip(可迭代对象1, 可迭代对象2)
python
# 使用 zip() 创建字典
keys = ['name', 'age', 'city']
values = ['Dave', 22, 'San Francisco']
dict5 = dict(zip(keys, values))
print(dict5)
# 输出: {'name': 'Dave', 'age': 22, 'city': 'San Francisco'}
2.5、通过fromkeys创建值为空的字典
fromkeys()
方法可以创建一个新字典,其中键来自给定的可迭代对象,而所有的值都是同一指定值(默认是None
)。
python
# 使用 fromkeys 创建字典
keys = ['name', 'age', 'city']
dict6 = dict.fromkeys(keys)
print(dict6)
# 输出: {'name': None, 'age': None, 'city': None}
# 使用 fromkeys 创建字典并指定默认值
dict7 = dict.fromkeys(keys, 'unknown')
print(dict7)
# 输出: {'name': 'unknown', 'age': 'unknown', 'city': 'unknown'}
三、字典元素的访问
3.1、通过 [键] 获得"值"
若键不存在,则抛出异常。
python
a = {'name':'zhangsan','age':18,'job':'programmer'}
b = a['name']
print(b)#zhangsan
3.2、通过get()方法获得
推荐使用。优点是:指定键不存在,返回None;也可以设定指定键不存在时默认返回的对象。推荐使用get()获取"值对象"
python
a = {'name':'zhangsan','age':18,'job':'programmer'}
b = a.get('name')
c = a.get('gender','不存在')
print(b)#zhangsan
print(c)#不存在
3.3、列出所有的键值对
python
a = {'name':'zhangsan','age':18,'job':'programmer'}
b = a.items()
print(b) #dict_items([('name', 'zhangsan'), ('age', 18), ('job', 'programmer')])
3.4、列出所有的键,列出所有的值
python
a = {'name':'zhangsan','age':18,'job':'programmer'}
k = a.keys()
v = a.values()
print(k) #dict_keys(['name', 'age', 'job'])
print(v) #dict_values(['zhangsan', 18, 'programmer'])
3.5、len() 键值对的个数
python
a = {'name':'zhangsan','age':18,'job':'programmer'}
num = len(a)
print(num) #3
3.6、检测一个"键"是否在字典中
python
a = {'name':'zhangsan','age':18,'job':'programmer'}
print("name" in a) #True
四、字典的添加、修改和删除
4.1、添加
给字典新增"键值对"。如果"键"已经存在,则覆盖旧的键值对;如果"键"不存在,则新增"键值对"
python
a = {'name':'张三','age':18,'job':'programmer'}
a['address']='北京'
a['age']=16
print(a)
#{'name': '张三', 'age': 16, 'job': 'programmer', 'address': '北京'}
4.2、修改
python语言中,字典是可变类型,python的修改是在原来的数据之上 进行修改。
python语言对应字典的修改,也提供了两种修改的方式:
(1) 使用[]的形式进行修改
dict[old_key] = new_value
(2) 使用update进行修正
dict.update({old_key : new_value})
4.2.1、使用[]的形式进行修改
使用方括号
[]
可以直接访问和修改字典中的某个键的值。如果键存在,赋值会更新该键对应的值;如果键不存在,则会添加一个新的键值对。
python
# 创建一个字典
my_dict = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 修改已存在的键
my_dict["age"] = 31 # 更新 age
print(my_dict)
# 输出: {'name': 'Alice', 'age': 31, 'city': 'New York'}
# 添加新的键值对
my_dict["country"] = "USA" # 添加新键 country
print(my_dict)
# 输出: {'name': 'Alice', 'age': 31, 'city': 'New York', 'country': 'USA'}
4.2.2、 使用update进行修正
update()
方法用于更新字典。它可以接收一个字典作为参数,将参数字典中的键值对更新到原字典中。如果原字典中已经存在某个键,则会更新该键对应的值;如果不存在,则添加新的键值对。此外,update()
方法同样支持传入关键字参数。
python
# 创建一个字典
my_dict = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 使用 update() 方法更新字典
my_dict.update({"age": 31, "city": "Los Angeles"}) # 更新 age 和 city
print(my_dict)
# 输出: {'name': 'Alice', 'age': 31, 'city': 'Los Angeles'}
# 添加新的键值对
my_dict.update({"country": "USA"}) # 添加新键 country
print(my_dict)
# 输出: {'name': 'Alice', 'age': 31, 'city': 'Los Angeles', 'country': 'USA'}
# 也可以使用关键字参数
my_dict.update(name="Bob", job="Engineer") # 更新 name 并添加 job
print(my_dict)
# 输出: {'name': 'Bob', 'age': 31, 'city': 'Los Angeles', 'country': 'USA', 'job': 'Engineer'}
4.3、删除
python语言对于字典的修改,提供了四种方式:
(1) pop():删除键值对儿
(2) del(): 根据字典的key进行删除
(3) clear(): 删除字典中所有的key:value
(4) popitem()随机删除和返回该键值对
4.3.1、pop():删除键值对儿
pop()
方法用于删除指定键的键值对,并返回该键对应的值。如果指定的键不存在,则会抛出KeyError
异常。
python
# 创建字典
my_dict = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 使用 pop() 删除并获取 age 的值
age = my_dict.pop("age")
print(age) # 输出: 30
print(my_dict) # 输出: {'name': 'Alice', 'city': 'New York'}
# 尝试删除一个不存在的键会抛出错误
# my_dict.pop("country") # 会抛出 KeyError
4.3.2、del(): 根据字典的key进行删除
del
关键字可以用来删除字典中的键值对,如果指定的键不存在,会抛出KeyError
。
python
# 创建字典
my_dict = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 使用 del 删除 city 键值对
del my_dict["city"]
print(my_dict) # 输出: {'name': 'Alice', 'age': 30}
# del 尝试删除不存在的键会抛出错误
# del my_dict["country"] # 会抛出 KeyError
4.3.3、clear(): 删除字典中所有的key:value
clear()
方法用于清空字典,将所有键值对删除,结果是一个空字典。
python
# 创建字典
my_dict = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 使用 clear() 删除所有键值对
my_dict.clear()
print(my_dict) # 输出: {}
4.3.4、popitem()随机删除和返回该键值对
字典是"无序可变序列",因此没有第一个元素、最后一个元素的概念;
popitem
弹出随机的项,因为字典并没有"最后的元素"或者其他有关顺序的概念。若想一个接一个地移除并处理项,这个方法就非常有效(因为不用首先获取键的列表)
python
# 创建字典
my_dict = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 使用 popitem() 删除并返回最后一个键值对
item = my_dict.popitem()
print(item) # 输出: ('city', 'New York'),具体输出顺序可能因字典的状态而异
print(my_dict) # 输出: {'name': 'Alice', 'age': 30}
# 如果字典为空,以下代码会抛出 KeyError
# my_dict.clear()
# my_dict.popitem() # 会抛出 KeyError
五、解包
序列解包用于字典时,默认是对"键"进行操作; 如果需要对键值对操作,则需要使用items();如果需要对"值"进行操作,则需要使用values();
python
s = {'name':'zhangsan','age':18,'job':'teacher'}
name,age,job=s #默认对键进行操作
print(name) #name
name,age,job=s.items() #对键值对进行操作
print(name) #('name', 'zhangsan')
name,age,job=s.values() #对值进行操作
print(name) #zhangsan