Python基础-5.字典

TOC

一、字典的基本使用

字典是另一种可变容器模型,且可存储任意类型对象。
字典的每个键值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并设置为default
  • dict.pop(key[, default]):删除key并返回对应的value,如果key不存在且没设置default,会报错
  • dict.popitem():随机删除并返回一个键值对(Python 3.7+ 中是删除最后插入的)
  • dict.clear():清空整个字典
  • dict.copy():返回字典的浅拷贝
  • dict.fromkeys(seq[, value]):创建一个新字典,key 来自 seq,默认值为 value
  • dict.__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'>
'''