程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Python 基础

    • 环境搭建
    • 标识符
    • 变量
    • 缩进和注释
    • 数据类型
    • 数据类型转换
    • 运算符
    • 字符串
    • 列表
    • 元组
    • 字典
      • 1. 字典的核心概念
      • 2. 创建字典
        • 2.1 使用花括号 {}
        • 2.2 使用 dict() 构造函数
      • 3. 访问字典元素:查
        • 3.1 使用方括号 []
        • 3.2 使用 .get() 方法 (推荐)
      • 4. 添加与修改字典元素:增 & 改
        • 使用 .update() 合并字典
        • Python 3.9+ 的合并运算符
      • 5. 删除字典元素:删
        • 5.1 del 关键字
        • 5.2 .pop() 方法
        • 5.3 .popitem() 方法
        • 5.4 .clear() 方法
      • 6. 遍历字典
        • 6.1 遍历键 (Key)
        • 6.2 遍历值 (Value)
        • 6.3 遍历键值对 (Item)
      • 7. 字典视图 (Views)
      • 8. 字典推导式 (Dictionary Comprehension)
      • 9. 更多高级方法
        • 9.1 .setdefault(key, default)
        • 9.2 dict.fromkeys(iterable, value=None)
      • 10. 字典的复制:浅拷贝与深拷贝
        • 10.1 浅拷贝 (.copy() 或 dict())
        • 10.2 深拷贝 (copy.deepcopy())
    • 集合
    • if判断
    • for循环
    • while循环
    • 循环综合练习
    • Python函数
    • 函数与循环实战
    • 生成式
    • 文件读写
    • 面向对象
    • 面向对象综合案例
  • Python 进阶

  • Python
  • Python 基础
scholar
2025-07-20
目录

字典

# 字典(Dictionary)


# 1. 字典的核心概念

字典(Dictionary)是 Python 中一种极其灵活的数据结构,它以 键-值对 (key-value pair) 的形式存储数据。

你可以把它想象成一本真实的字典或电话簿:

  • 键 (Key): 就像字典里的单词或电话簿里的人名。键必须是唯一的且不可变的。最常用的键是字符串和数字。
  • 值 (Value): 就像单词的释义或人名的电话号码。值可以是任意类型的数据,比如数字、字符串、列表,甚至另一个字典。

为什么键必须是不可变的? 字典的内部工作原理依赖于对键进行“哈希(hash)”计算,以实现快速查找。只有不可变的对象(如字符串、数字、元组)才能保证其哈希值永不改变。如果键是可变的(如列表),它的内容一旦改变,哈希值也会变,字典就无法再找到它了。

字典的核心特性:

  • 无序 (Unordered): 在 Python 3.7 之前,字典是完全无序的。从 Python 3.7 开始,字典会记住元素的插入顺序。但我们通常不应该依赖这个顺序,而是通过键来访问数据。
  • 可变 (Mutable): 字典在创建后,可以随时添加、修改或删除键值对。
  • 通过键访问: 字典通过键来查找对应的值。这个操作的平均时间复杂度是 O(1),意味着无论字典有多大,查找速度都几乎是恒定的,非常快。

# 2. 创建字典

# 2.1 使用花括号 {}

这是最常见的创建方式。

# 创建一个空字典
empty_dict = {}
print(f"空字典: {empty_dict}") # 输出: 空字典: {}

# 创建一个包含键值对的字典
person = {
    "name": "Alice",
    "age": 25,
    "city": "New York"
}
print(f"个人信息字典: {person}") # 输出: 个人信息字典: {'name': 'Alice', 'age': 25, 'city': 'New York'}
1
2
3
4
5
6
7
8
9
10
11

# 2.2 使用 dict() 构造函数

dict() 提供了多种灵活的创建方式。

# 1. 通过关键字参数创建 (键必须是合法的变量名)
person_alt = dict(name="Bob", age=30)
print(f"关键字参数创建: {person_alt}") # 输出: 关键字参数创建: {'name': 'Bob', 'age': 30}

# 2. 通过包含元组的列表创建
items = [("fruit", "apple"), ("color", "red")]
from_list = dict(items)
print(f"从元组列表创建: {from_list}") # 输出: 从元组列表创建: {'fruit': 'apple', 'color': 'red'}

# 3. 通过 zip 函数将两个列表合并成字典
keys = ["a", "b", "c"]
values = [1, 2, 3]
from_zip = dict(zip(keys, values))
print(f"从 zip 对象创建: {from_zip}") # 输出: 从 zip 对象创建: {'a': 1, 'b': 2, 'c': 3}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3. 访问字典元素:查

场景对比: [] vs .get()

  • 场景一:你确信键一定存在。 比如,处理一个结构固定的数据。此时使用 [] 更直接,代码也更简洁。
  • 场景二:你不确定键是否存在。 比如,处理用户输入或外部API返回的数据。此时必须使用 .get(),并提供一个合理的默认值,以防止程序因 KeyError 而崩溃。

# 3.1 使用方括号 []

这是最直接的访问方式。如果键不存在,会立即抛出 KeyError 错误。

person = {"name": "Alice", "age": 25}

print(f"姓名: {person['name']}") # 输出: 姓名: Alice

# 尝试访问一个不存在的键会引发错误
# print(person['gender']) # 这行代码会取消注释后会抛出 KeyError: 'gender'
1
2
3
4
5
6

# 3.2 使用 .get() 方法 (推荐)

.get(key, default=None) 是更安全、更灵活的访问方式。

person = {"name": "Alice", "age": 25}

print(f"年龄: {person.get('age')}") # 输出: 年龄: 25
print(f"性别: {person.get('gender')}") # 输出: 性别: None (键不存在,返回默认的 None)
print(f"城市: {person.get('city', 'Unknown')}") # 输出: 城市: Unknown (键不存在,返回你指定的默认值)
1
2
3
4
5

# 4. 添加与修改字典元素:增 & 改

字典的添加和修改操作使用同一种语法,非常直观。

person = {"name": "Alice", "age": 25}

# 添加新键值对 (因为 'city' 键不存在)
person["city"] = "New York"
print(f"添加城市后: {person}") # 输出: 添加城市后: {'name': 'Alice', 'age': 25, 'city': 'New York'}

# 修改已存在的键的值 (因为 'age' 键已存在)
person["age"] = 26
print(f"修改年龄后: {person}") # 输出: 修改年龄后: {'name': 'Alice', 'age': 26, 'city': 'New York'}
1
2
3
4
5
6
7
8
9

# 使用 .update() 合并字典

.update() 方法可以将另一个字典或一个包含键值对的可迭代对象(如元组列表)合并到当前字典中。

profile = {"name": "Charlie", "gender": "Male"}
contact_info = {"email": "charlie@example.com", "name": "Charles"} # 注意 'name' 键重复

profile.update(contact_info) # contact_info 中的键值对会覆盖 profile 中的
print(f"更新后的个人资料: {profile}")
# 输出: 更新后的个人资料: {'name': 'Charles', 'gender': 'Male', 'email': 'charlie@example.com'}
1
2
3
4
5
6

# Python 3.9+ 的合并运算符

在 Python 3.9 及以上版本中,你可以使用更简洁的 | 和 |= 运算符来合并字典。

dict_a = {'a': 1, 'b': 2}
dict_b = {'b': 3, 'c': 4}

# |: 创建一个新字典,不修改原始字典
merged_dict = dict_a | dict_b
print(f"使用 | 合并: {merged_dict}") # 输出: 使用 | 合并: {'a': 1, 'b': 3, 'c': 4}
print(f"dict_a 未改变: {dict_a}") # 输出: dict_a 未改变: {'a': 1, 'b': 2}

# |=: 原地更新字典
dict_a |= dict_b
print(f"使用 |= 更新: {dict_a}") # 输出: 使用 |= 更新: {'a': 1, 'b': 3, 'c': 4}
1
2
3
4
5
6
7
8
9
10
11

# 5. 删除字典元素:删

方法 描述 键不存在时 返回值
del my_dict[key] 直接删除键值对 抛出 KeyError 无
my_dict.pop(key) 删除键值对 抛出 KeyError 被删除的值
my_dict.pop(key, default) 安全地删除 返回 default 被删除的值或 default
my_dict.popitem() 删除最后一项 抛出 KeyError 被删除的 (key, value) 元组

# 5.1 del 关键字

person = {"name": "Alice", "age": 25, "city": "New York"}
del person["city"]
print(f"删除 city 后: {person}") # 输出: 删除 city 后: {'name': 'Alice', 'age': 25}
1
2
3

# 5.2 .pop() 方法

person = {"name": "Alice", "age": 25}
removed_age = person.pop("age")
print(f"被删除的年龄: {removed_age}") # 输出: 被删除的年龄: 25
print(f"pop('age') 后: {person}")    # 输出: pop('age') 后: {'name': 'Alice'}

# 安全地 pop
removed_city = person.pop("city", "Not Found")
print(f"尝试删除 city: {removed_city}") # 输出: 尝试删除 city: Not Found
1
2
3
4
5
6
7
8

# 5.3 .popitem() 方法

person = {"name": "Alice", "age": 25, "city": "New York"}
last_item = person.popitem()
print(f"被删除的最后一项: {last_item}") # 输出: 被删除的最后一项: ('city', 'New York')
print(f"popitem() 后: {person}")       # 输出: popitem() 后: {'name': 'Alice', 'age': 25}
1
2
3
4

# 5.4 .clear() 方法

person = {"name": "Alice", "age": 25}
person.clear()
print(f"clear() 之后: {person}") # 输出: clear() 之后: {}
1
2
3

# 6. 遍历字典

# 6.1 遍历键 (Key)

直接 for key in my_dict: 是最常用和最简洁的方式。

person = {"name": "Alice", "age": 25}
for key in person:
    print(f"键: {key}")
# 输出:
# 键: name
# 键: age
1
2
3
4
5
6

# 6.2 遍历值 (Value)

使用 .values() 方法获取所有值的视图。

for value in person.values():
    print(f"值: {value}")
# 输出:
# 值: Alice
# 值: 25
1
2
3
4
5

# 6.3 遍历键值对 (Item)

使用 .items() 方法是同时获取键和值的最佳方式。它返回包含 (key, value) 元组的视图。

# 使用元组解包,代码非常优雅
for key, value in person.items():
    print(f"{key} -> {value}")
# 输出:
# name -> Alice
# age -> 25
1
2
3
4
5
6

# 7. 字典视图 (Views)

.keys(), .values(), .items() 返回的不是列表,而是特殊的视图对象。

视图对象的关键特性是动态性:如果原始字典发生改变,视图会立即反映这些变化。这使得它们非常节省内存,因为不需要每次都复制数据。

person = {"name": "Alice", "age": 25}
keys_view = person.keys()

print(f"添加前的视图: {keys_view}") # 输出: 添加前的视图: dict_keys(['name', 'age'])

# 修改原始字典
person["city"] = "New York"

# 视图会自动更新,无需重新获取
print(f"添加后的视图: {keys_view}") # 输出: 添加后的视图: dict_keys(['name', 'age', 'city'])
1
2
3
4
5
6
7
8
9
10

# 8. 字典推导式 (Dictionary Comprehension)

与列表推导式类似,字典推导式可以用一行代码优雅地创建字典。

基本语法: {key_expression: value_expression for item in iterable}

# 创建一个数字及其平方的字典
squares = {x: x**2 for x in range(1, 6)}
print(f"平方数字典: {squares}") # 输出: 平方数字典: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 从列表中筛选数据
fruits = ["apple", "banana", "cherry"]
fruit_lengths = {f: len(f) for f in fruits if len(f) > 5}
print(f"长度大于5的水果: {fruit_lengths}") # 输出: 长度大于5的水果: {'banana': 6, 'cherry': 6}

# 键值互换
original_dict = {'a': 1, 'b': 2}
swapped_dict = {v: k for k, v in original_dict.items()}
print(f"键值互换后: {swapped_dict}") # 输出: 键值互换后: {1: 'a', 2: 'b'}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 9. 更多高级方法

# 9.1 .setdefault(key, default)

这个方法非常有用,它用一行代码解决了“检查-设置-获取”的常见模式。

# 传统写法: 需要 if 判断
data = {}
if 'items' not in data:
    data['items'] = []
data['items'].append('item1')

# 使用 setdefault 的优雅写法
data = {}
# 如果 'items' 键不存在,则创建一个空列表[]并设为其值,然后返回这个列表
# 如果 'items' 键已存在,则直接返回其对应的值(已存在的列表)
data.setdefault('items', []).append('item1')
data.setdefault('items', []).append('item2')

print(f"使用setdefault构建列表: {data}") # 输出: 使用setdefault构建列表: {'items': ['item1', 'item2']}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 9.2 dict.fromkeys(iterable, value=None)

这是一个类方法,用于快速创建一个新字典,其键来自一个可迭代对象,所有键共享同一个值。

keys = ["name", "age", "city"]
# 创建一个所有值都为 "unknown" 的字典
default_person = dict.fromkeys(keys, "unknown")
print(f"默认字典: {default_person}") 
# 输出: 默认字典: {'name': 'unknown', 'age': 'unknown', 'city': 'unknown'}

# 如果不提供值,默认为 None
none_dict = dict.fromkeys(keys)
print(f"值为None的字典: {none_dict}")
# 输出: 值为None的字典: {'name': None, 'age': None, 'city': None}
1
2
3
4
5
6
7
8
9
10

# 10. 字典的复制:浅拷贝与深拷贝

警告: 字典的复制是初学者极易出错的地方。如果你的字典的值包含了列表或另一个字典等可变类型,请务必小心。

# 10.1 浅拷贝 (.copy() 或 dict())

只复制字典的顶层,如果值是可变对象(如列表、字典),则只复制其引用。修改嵌套对象会影响到原始字典。

original = {"user": "Alice", "data": [1, 2]}
shallow_copy = original.copy()

shallow_copy["data"].append(3) # 修改嵌套列表

print(f"原始字典: {original}")       # 输出: 原始字典: {'user': 'Alice', 'data': [1, 2, 3]} (被意外修改!)
print(f"浅拷贝字典: {shallow_copy}") # 输出: 浅拷贝字典: {'user': 'Alice', 'data': [1, 2, 3]}
1
2
3
4
5
6
7

# 10.2 深拷贝 (copy.deepcopy())

递归地复制所有层级的元素,创建一个与原始对象完全独立的新字典。

import copy
original = {"user": "Alice", "data": [1, 2]}
deep_copy = copy.deepcopy(original)

deep_copy["data"].append(3) # 修改嵌套列表

print(f"原始字典: {original}")     # 输出: 原始字典: {'user': 'Alice', 'data': [1, 2]} (安全!)
print(f"深拷贝字典: {deep_copy}") # 输出: 深拷贝字典: {'user': 'Alice', 'data': [1, 2, 3]}
1
2
3
4
5
6
7
8
编辑此页 (opens new window)
上次更新: 2025/07/23, 06:33:16
元组
集合

← 元组 集合→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式