Python基础-5.字典
一、字典的基本使用
字典是另一种可变容器模型,且可存储任意类型对象。
字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,分割,整个字典包括在花括号{}中。
字典特性
字典值可以是任何的python对象,既可以是标准的对象,也可以是用户定义的,但键不行。
不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住。
键必须不可变,所以可以用数字,字符串或元组充当,而用列表就不行。
字典的赋值
可以通过=符号或dict()函数创建字典,如下所示:
# 创建一个空字典
d0 = {}
# 创建一个标准字典
d1 = {'name': 'martin', 'age': 66, 'firstname': 'jeffry'}
# 使用dict()函数创建字典
d2 = dict()
注意:
dict作为Python的关键字和内置函数,变量名不建议命名为dict。
字典的取值
1.普通获取
就跟列表取值差不多,只不过索引值从0到往上变成了key的值。
语法:
变量 = 字典名['key的值']
【示例】代码如下:
data = {'name': 'Jack', 'age': 18, 'city': 'chengdu'}
# 取key为name的value值
print('字典data中name的值为:', data['name'])
# 取key为age的value值
print('字典data中age的值为:', data['age'])
''' 运行结果如下
字典data中name的值为: Jack
字典data中age的值为: 18
'''
注意:当字典中使用不存在的键访问数据就会输出错误。
2.get()方法
也可以只是用get()方法来获取对应键的value值。
【示例】代码如下:
data = {'name': 'Jack', 'age': 18, 'city': 'chengdu'}
# 使用get()方法获取取key为name的value值
print('字典data中name的值为:', data.get('name'))
'''运行结果如下
字典data中name的值为: Jack
'''
字典可用内置函数
-
eval():能执行字符串里的Python表达式,比如把一个字典字符串转成字典。 -
ast.literal_eval():只会安全地解析字面量(数字、字符串、列表、字典等),不会执行代码。 -
dict():可以把键值对或可迭代对象转成字典。 -
len():计算字典元素个数,即键的总数。特别注意:
eval()方法会执行任意代码,存在安全风险,一般不推荐直接用。保险起见建议使用ast.literal_eval()方法替代。
【示例】
import ast
data = "{'name': 'Alice', 'age': 25}"
# 使用eval函数将字符串转换成字典
d1 = eval(data)
print(f'd1的值: {d1}, d1的类型: {type(d1)}')
# 使用ast.literal_eval函数将字符串转换成字典
d2 = ast.literal_eval(data)
print(f'd2的值: {d2}, d2的类型: {type(d2)}')
# 统计字典d1和d2的长度
print(f'd1的长度: {len(d1)}, d2的长度: {len(d2)}')
'''运行结果如下
d1的值: {'name': 'Alice', 'age': 25}, d1的类型: <class 'dict'>
d2的值: {'name': 'Alice', 'age': 25}, d2的类型: <class 'dict'>
d1的长度: 2, d2的长度: 2
'''
二、字典的操作
相比于列表来说,字典的数据结构会复杂一些,所以字典的操作也会相当于列表比较复杂一点。
字典的方法
dict.get(key, default=None):根据key获取value,如果key不存在,返回默认值,不会报错dict.keys():返回所有key的视图对象dict.values():返回所有value的视图对象dict.items():返回所有键值对 (key, value) 的视图对象dict.update([other]):用另一个字典或可迭代对象更新当前字典(同名 key 会被覆盖)dict.setdefault(key, default=None):如果key存在,返回其值;如果不存在,插入key并设置为defaultdict.pop(key[, default]):删除key并返回对应的value,如果key不存在且没设置default,会报错dict.popitem():随机删除并返回一个键值对(Python 3.7+ 中是删除最后插入的)dict.clear():清空整个字典dict.copy():返回字典的浅拷贝dict.fromkeys(seq[, value]):创建一个新字典,key 来自 seq,默认值为 valuedict.__contains__(key):判断key是否在字典中(等价于key in dict)
添加键值对
定义一个字典供下面示例使用:
data = {'name': 'Jack', 'age': 18, 'city': 'chengdu'}
1.赋值添加单个
新增时只要给一个新的key赋值即可。
【示例】代码如下:
# 添加一个键为hobby,value为drawing的键值对元素
data['hobby'] = 'drawing'
print('data的值:', data)
''' 运行结果如下
data的值: {'name': 'Jack', 'age': 18, 'city': 'chengdu', 'hobby': 'drawing'}
'''
2.update()方法
使用update()方法可以添加单个或者多个键值对元素。
【示例】代码如下:
# 使用update添加单个
data.update({"height": 187})
print('添加单个元素之后data的值:', data)
# 使用uodate添加多个
data.update({"gender": "female", "hobby": "music"})
print('添加多个元素之后data的值:', data)
''' 运行结果如下
添加单个元素之后data的值: {'name': 'Jack', 'age': 18, 'city': 'chengdu', 'height': 187}
添加多个元素之后data的值: {'name': 'Jack', 'age': 18, 'city': 'chengdu', 'height': 187, 'gender': 'female', 'hobby': 'music'}
'''
删除键值对
定义一个字典供下面示例使用:
data = {'name': 'Jack', 'age': 18, 'city': 'chengdu'}
1.pop()方法
使用pop()方法删除指定key,并返回对应的value。
【示例】代码如下:
data.pop('age')
print('使用pop()方法删除key为age后的字典:', data)
''' 运行结果如下
使用pop()方法删除key为age后的字典: {'name': 'Jack', 'city': 'chengdu'}
'''
2.popitem()方法
使用popitem()方法随机删除一个key-value(Python 3.7+ 是删除最后一个)。
【示例】代码如下:
data.popitem()
print('使用popitem()方法随机删除后的字典:', data)
''' 运行结果如下
使用popitem()方法随机删除后的字典: {'name': 'Jack', 'age': 18}
'''
3.del关键字
使用del关键字删除指定key。
【示例】代码如下:
del data['age']
print('使用del关键字删除key为age后的字典:', data)
''' 运行结果如下
使用del关键字删除key为age后的字典: {'name': 'Jack', 'city': 'chengdu'}
'''
4.clear()方法
使用clear()方法清除整个字典。
【示例】代码如下:
data.clear()
print('使用clear()方法清空后的字典:', data)
''' 运行结果如下
使用clear()方法清空后的字典: {}
'''
更新字典
修改和增加很像,如果key已经存在,赋值就是修改。
定义一个字典供下面示例使用:
data = {'name': 'Jack', 'age': 18, 'city': 'chengdu'}
1.赋值更新单个
使用赋值的方式修改对应key的值,只要赋值的key在原字典存在就可以修改该key的value值了。
【示例】代码如下:
# 修改data字典的age值为20
data['age'] = 20
print('修改之后的data字典的值:', data)
''' 运行结果如下
修改之后的data字典的值: {'name': 'Jack', 'age': 20, 'city': 'chengdu'}
'''
2.update()方法
修改和增加很像,如果key已经存在,赋值就是修改。
【示例】代码如下:
# 使用update修改age为20
data.update({"age": 20})
print('修改单个元素之后data的值:', data)
# 使用update修改age为21以及city为shanghai
data.update({"age": 21, "city": "shanghai"})
print('修改多个元素之后data的值:', data)
''' 运行结果如下
修改单个元素之后data的值: {'name': 'Jack', 'age': 20, 'city': 'chengdu'}
修改多个元素之后data的值: {'name': 'Jack', 'age': 21, 'city': 'shanghai'}
'''
遍历字典
定义一个字典供下面示例使用:
data = {'name': 'Jack', 'age': 18, 'city': 'chengdu'}
1.遍历所有的key
可以利用keys()方法获取字典中的所有key值。
【示例】代码如下:
for index, key in enumerate(data.keys(), start=1):
print(f'第{index}个key的值:', key)
''' 运行结果如下
第1个key的值: name
第2个key的值: age
第3个key的值: city
'''
2.遍历所有的value
可以利用value()方法获取字典中的所有value值。
【示例】代码如下:
for index, value in enumerate(data.values(), start=1):
print(f'第{index}个value的值:', value)
''' 运行结果如下
第1个value的值: Jack
第2个value的值: 18
第3个value的值: chengdu
'''
3.遍历整个字典
可以利用for循环语句去遍历所有的key过程中获取value的值。
【示例】代码如下:
for key in data:
value = data[key]
print('key的值:', key, ', value的值:', value)
''' 运行结果如下
key的值: name , value的值: Jack
key的值: age , value的值: 18
key的值: city , value的值: chengdu
'''
还可以利用for循环配合items()方法获取所有的key和value。
【示例】代码如下:
for key, value in data.items():
print('key的值:', key, ', value的值:', value)
''' 运行结果如下
key的值: name , value的值: Jack
key的值: age , value的值: 18
key的值: city , value的值: chengdu
'''
三、字典的进阶使用
字典的复制
字典的复制跟列表一样分为浅拷贝和深拷贝。下面也同样举个例子来说明列表在操作的情况下值的变化。
【示例】创建一个字典a,b复制等于a,操作字典a观察字典b的变化,再修改字典b同样观察字典a的值的变化
a = {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
b = a
print('a的值:', a)
print('b的值:', b)
# 修改a的值
a['age'] = 19
print('a的值:', a)
print('b的值:', b)
# 修改b的值
b["name"] = "Bob"
b["hobbies"].append("coding")
print('a的值:', a)
print('b的值:', b)
''' 运行结果如下
a的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
b的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
a的值: {'name': 'Alice', 'age': 19, 'hobbies': ['music', 'travel']}
b的值: {'name': 'Alice', 'age': 19, 'hobbies': ['music', 'travel']}
a的值: {'name': 'Bob', 'age': 19, 'hobbies': ['music', 'travel', 'coding']}
b的值: {'name': 'Bob', 'age': 19, 'hobbies': ['music', 'travel', 'coding']}
'''
字典的试验跟列表发生了同样的事件,直接赋值不会生成新字典,两个变量指向同一个对象,修改一个会影响另一个。
浅拷贝
字典的浅拷贝,会生成一个新的字典对象,但里面的可变对象(比如列表、字典)还是共享的。
一般浅拷贝会用dict.copy()、copy.copy()方法。
【示例】代码如下:
a = {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
b = a.copy()
print('a的值:', a)
print('b的值:', b)
# 使用浅拷贝修改a的值
a['age'] = 19
print('a的值:', a)
print('b的值:', b)
# 使用浅拷贝修改b的值
b["name"] = "Bob"
b["hobbies"].append("coding")
print('a的值:', a)
print('b的值:', b)
''' 运行结果如下
a的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
b的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
a的值: {'name': 'Alice', 'age': 19, 'hobbies': ['music', 'travel']}
b的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
a的值: {'name': 'Alice', 'age': 19, 'hobbies': ['music', 'travel', 'coding']}
b的值: {'name': 'Bob', 'age': 18, 'hobbies': ['music', 'travel', 'coding']}
'''
总结:无论是修改a的age这个key还是修改b的name(不可变类型),不会影响另外的字典,但是修改hobbies(列表,可变类型),会影响原字典。
深拷贝
深拷贝会递归复制整个对象及其子对象,完全独立。
字典的深拷贝跟列表一样,使用copy.deepcopy()方法即可。
【示例】代码如下:
from copy import deepcopy
a = {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
b = deepcopy(a)
print('a的值:', a)
print('b的值:', b)
# 使用浅拷贝修改a的值
a['age'] = 19
a["hobbies"].append("dance")
print('a的值:', a)
print('b的值:', b)
# 使用浅拷贝修改b的值
b["name"] = "Bob"
b["hobbies"].append("coding")
print('a的值:', a)
print('b的值:', b)
''' 运行结果如下
a的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
b的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
a的值: {'name': 'Alice', 'age': 19, 'hobbies': ['music', 'travel', 'dance']}
b的值: {'name': 'Alice', 'age': 18, 'hobbies': ['music', 'travel']}
a的值: {'name': 'Alice', 'age': 19, 'hobbies': ['music', 'travel', 'dance']}
b的值: {'name': 'Bob', 'age': 18, 'hobbies': ['music', 'travel', 'coding']}
'''
总结:深拷贝时,a和b的hobbies列表被独立复制,所以无论修改a还是b的列表都不会影响另外一个字典中的列表。
字典的嵌套
跟列表一样,字典的value部分也可以对各种类型的Python对象进行嵌套使用,除了常见的数字、浮点、字符串等数据类型,还可以是列表本身、字典等数据类型。
【示例】一个包含多层嵌套包含各种类型的数据结构字典
data = {
"user": {
"id": 1001,
"name": "Alice",
"active": True,
"roles": ["admin", "editor", "viewer"],
"profile": {
"age": 25,
"city": "Beijing",
"hobbies": ["music", "travel", "coding"]
},
"projects": [
{"name": "Project A", "status": "ongoing", "members": 5},
{"name": "Project B", "status": "completed", "members": 12}
]
}
}
JSON数据转换
字典在Python中的作用是很广泛的,尤其是字典可用于JSON数据格式的转换。
使用的转换方法:
json.loads():如果字符串是JSON格式(双引号),可以用json.loads()转成字典。json.dumps():标准的字典数据类型,可以将字典转换成JSON数据格式。
【示例】代码如下:
import json
json_data = '{"name": "Jack", "age": 18}'
dict_data = {"name": "Bob", "age": 20}
d1 = json.loads(json_data)
j1 = json.dumps(dict_data)
print(d1, type(d1))
print(j1, type(j1))
''' 运行结果如下
{'name': 'Jack', 'age': 18} <class 'dict'>
{"name": "Bob", "age": 20} <class 'str'>
'''