深入理解Python字典(Dictionary):从基础操作到高级应用

深入理解Python字典(Dictionary):从基础操作到高级应用

flyfish

一、Python 字典(Dictionary)基本概念

1. 定义

Python 字典是一种可变、无序的数据结构,用于存储键值对(key - value pairs)。每个键(key)必须是唯一的,且不可变(如字符串、数字或完全不可变的元组),而值(value)可以是任意类型,包括列表、字典等。

2. 特点
  • 键的唯一性:字典中不允许有重复的键,如果尝试使用相同的键进行赋值,后面的值会覆盖前面的值。
  • 无序性:在 Python 3.6 之前,字典是无序的,即键值对的存储顺序和插入顺序无关;从 Python 3.6 开始,字典会保持插入顺序,但这只是一个实现细节,在 Python 3.7 及以后版本才正式成为语言规范。
  • 高效查找:通过键可以快速访问对应的值,平均时间复杂度为 O ( 1 ) O(1) O(1)
3. 用途

字典常用于存储和检索具有关联关系的数据,例如配置信息、数据库记录、统计计数等。

二、使用方法

1. 字典的创建与初始化
  • 使用花括号
# 创建一个空字典
empty_dict = {}
# 创建包含键值对的字典
person = {'name': 'Bob', 'age': 25, 'city': 'New York'}
  • 使用 dict() 构造函数
# 从键值对元组列表创建字典
dict_from_list = dict([('a', 1), ('b', 2)])
# 从关键字参数创建字典
dict_from_kwargs = dict(name='Charlie', age=30)
# 使用 fromkeys 方法创建字典
keys = ('name', 'age', 'city')
new_dict = dict.fromkeys(keys, 'unknown')  # 创建一个字典,所有值初始化为'unknown'
2. 字典的基本操作
  • 访问元素
person = {'name': 'Bob', 'age': 25}
# 使用键访问值
print(person['name'])  # 输出: Bob
# 使用 get() 方法安全访问值
print(person.get('city', 'Unknown'))  # 输出: Unknown
# 使用 setdefault 方法设置默认值
city = person.setdefault('city', 'Unknown')  # 如果'city'键不存在,则设置并返回'Unknown'
  • 添加和修改元素
person = {'name': 'Bob', 'age': 25}
# 添加新的键值对
person['city'] = 'New York'
# 修改已有键的值
person['age'] = 26
  • 删除元素
person = {'name': 'Bob', 'age': 25, 'city': 'New York'}
# 使用 del 语句删除键值对
del person['city']
# 使用 pop() 方法删除键值对并返回值
age = person.pop('age')
# 使用 popitem() 方法随机删除并返回一个键值对
last_item = person.popitem()
3. 字典的常用方法
  • keys()values()items()
person = {'name': 'Bob', 'age': 25}
# 获取所有键
print(person.keys())  # 输出: dict_keys(['name', 'age'])
# 获取所有值
print(person.values())  # 输出: dict_values(['Bob', 25])
# 获取所有键值对
print(person.items())  # 输出: dict_items([('name', 'Bob'), ('age', 25)])
  • update()
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
# 将 dict2 的键值对更新到 dict1 中
dict1.update(dict2)
print(dict1)  # 输出: {'a': 1, 'b': 3, 'c': 4}
  • clear()
person = {'name': 'Bob', 'age': 25}
# 清空字典
person.clear()
print(person)  # 输出: {}
4. 字典的遍历
  • 遍历键
person = {'name': 'Bob', 'age': 25}
for key in person:
    print(key)
  • 遍历值
person = {'name': 'Bob', 'age': 25}
for value in person.values():
    print(value)
  • 遍历键值对
person = {'name': 'Bob', 'age': 25}
for key, value in person.items():
    print(key, value)
5. 字典的嵌套
students = {
    'Alice': {'age': 20, 'grades': [85, 90, 78]},
    'Bob': {'age': 21, 'grades': [70, 80, 85]}
}
print(students['Alice']['grades'])  # 输出: [85, 90, 78]
6. 字典的排序
student_scores = {'Alice': 85, 'Bob': 70, 'Charlie': 90}
# 按键排序
sorted_by_key = sorted(student_scores.items())
# 按值排序
sorted_by_value = sorted(student_scores.items(), key=lambda item: item[1])

三、理论

1. 数据结构基础 - 哈希表

Python 字典是基于哈希表(Hash Table)实现的。哈希表是一种根据键(key)直接访问内存存储位置的数据结构,它通过哈希函数(Hash Function)将键映射到存储桶(Bucket)或槽(Slot)中,以此实现高效的数据存储和查找。

2. 哈希函数

哈希函数是哈希表的核心,它接受一个键作为输入,然后返回一个固定范围的整数,这个整数就是键对应的哈希值(Hash Value)。在 Python 中,内置的 hash() 函数可以计算大多数不可变对象的哈希值。不同的键通过哈希函数计算得到的哈希值可能相同,这种情况称为哈希冲突(Hash Collision)。Python 字典使用开放寻址法(Open Addressing)来解决哈希冲突,即当发生冲突时,会在哈希表中寻找下一个可用的槽位。

3. 字典的存储和查找过程
  • 存储过程
    • 计算哈希值:使用哈希函数计算键的哈希值。
    • 确定槽位:通过哈希值和哈希表的大小,确定键值对应该存储的槽位。
    • 处理冲突:如果该槽位已经被占用(发生哈希冲突),则使用开放寻址法寻找下一个可用的槽位。
    • 存储键值对:将键值对存储到找到的槽位中。
  • 查找过程
    • 计算哈希值:使用相同的哈希函数计算键的哈希值。
    • 确定槽位:根据哈希值和哈希表的大小,找到对应的槽位。
    • 检查键是否匹配:如果该槽位存储的键与查找的键相同,则返回对应的值;如果不相同,则使用开放寻址法继续查找下一个槽位,直到找到匹配的键或遍历完整个哈希表。
4. 动态扩容机制

为了保证哈希表的性能,Python 字典会在必要时进行动态扩容。当哈希表的填充因子(即已使用的槽位数与总槽位数的比值)超过一定阈值(通常是 2/3)时,字典会自动进行扩容操作:

  • 创建新的哈希表:创建一个更大的哈希表,通常是原哈希表大小的两倍。
  • 重新哈希:将原哈希表中的所有键值对重新计算哈希值,并插入到新的哈希表中。此过程可能会导致性能下降,因此选择合适的初始容量以减少扩容次数是很重要的。
5. 键的不可变性要求

Python 字典要求键必须是不可变对象(如字符串、数字、完全不可变的元组),这是因为哈希表的工作原理依赖于键的哈希值的稳定性。如果键是可变对象(如列表、字典),那么在对象状态改变后,其哈希值也会改变,这会导致在查找或删除键值对时出现错误。需要注意的是,即使元组可以用作字典的键,但如果元组内包含可变对象(例如列表),则整个元组也是不可作为字典键的,因为这样的元组不是完全不可变的。

四、完整示例代码

# 创建字典
student = {'name': 'Alice', 'age': 20, 'grades': [85, 90, 78]}

# 访问元素
print(student['name'])  # 输出: Alice
print(student.get('city', 'Unknown'))  # 输出: Unknown
city = student.setdefault('city', 'Los Angeles')  # 设置默认城市

# 添加和修改元素
student['city'] = 'Los Angeles'
student['age'] = 21

# 删除元素
del student['grades']
age = student.pop('age')

# 使用常用方法
print(student.keys())  # 输出: dict_keys(['name', 'city'])
print(student.values())  # 输出: dict_values(['Alice', 'Los Angeles'])
print(student.items())  # 输出: dict_items([('name', 'Alice'), ('city', 'Los Angeles')])

# 遍历字典
for key, value in student.items():
    print(key, value)

# 字典嵌套
students = {
    'Alice': {'age': 20, 'grades': [85, 90, 78]},
    'Bob': {'age': 21, 'grades': [70, 80, 85]}
}
print(students['Alice']['grades'])  # 输出: [85, 90, 78]

# 字典排序
student_scores = {'Alice': 85, 'Bob': 70, 'Charlie': 90}
sorted_by_key = sorted(student_scores.items())
sorted_by_value = sorted(student_scores.items(), key=lambda item: item[1])
print(sorted_by_key)
print(sorted_by_value)

五、字典推导式(Dictionary Comprehension)

字典推导式(Dictionary Comprehension)是 Python 中一种简洁、高效的创建字典的方式,它允许你使用一行代码从可迭代对象(如列表、元组、集合等)中创建字典,其语法类似于列表推导式和集合推导式。

基本语法

字典推导式的基本语法结构如下:

{key_expression: value_expression for item in iterable if condition}
  • key_expression:用于生成字典的键的表达式。
  • value_expression:用于生成字典的值的表达式。
  • item:可迭代对象中的每个元素。
  • iterable:可迭代对象,如列表、元组、集合等。
  • if condition:可选的条件表达式,用于筛选符合条件的元素,只有满足条件的元素才会被用于生成字典。
示例及解释
1. 简单的字典推导式

假设你有两个列表,一个存储学生的名字,另一个存储对应的成绩,你可以使用字典推导式将它们组合成一个字典。

names = ['Alice', 'Bob', 'Charlie']
scores = [85, 90, 78]

student_scores = {name: score for name, score in zip(names, scores)}
print(student_scores)

解释

  • zip(names, scores)namesscores 列表中的元素一一对应,形成元组。
  • for name, score in zip(names, scores) 遍历这些元组,将每个元组中的第一个元素赋值给 name,第二个元素赋值给 score
  • {name: score}name 为键,score 为值创建字典的键值对。
2. 带有条件的字典推导式

假设你只想将成绩大于 80 分的学生信息存储到字典中,可以添加条件表达式。

names = ['Alice', 'Bob', 'Charlie']
scores = [85, 90, 78]

high_score_students = {name: score for name, score in zip(names, scores) if score > 80}
print(high_score_students)

解释

  • if score > 80 是条件表达式,只有当 score 大于 80 时,对应的 namescore 才会被添加到字典中。
3. 使用字典推导式对现有字典进行转换

假设你有一个字典,存储了学生的名字和成绩,你想将成绩转换为对应的等级(A: 90 - 100, B: 80 - 89, C: 70 - 79)。

student_scores = {'Alice': 85, 'Bob': 90, 'Charlie': 78}

grade_dict = {name: 'A' if score >= 90 else 'B' if score >= 80 else 'C' for name, score in student_scores.items()}
print(grade_dict)

解释

  • student_scores.items() 返回字典的键值对元组。
  • for name, score in student_scores.items() 遍历这些键值对。
  • 'A' if score >= 90 else 'B' if score >= 80 else 'C' 是一个三元表达式,根据成绩确定对应的等级。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二分掌柜的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值