Repository navigation
Expand file tree
/
Copy path1_3_data_structures.py
More file actions
265 lines (203 loc) · 8.86 KB
/
Copy path1_3_data_structures.py
File metadata and controls
265 lines (203 loc) · 8.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
================================================================
零基础起步 · 1.3 数据结构(list、tuple、dict、set)
================================================================
【课程属性】L0 · 必修 · 预计 100~140 分钟
【前置要求】完成 1.2;会使用类型、运算、字符串和下标
【学习目标】
1. 根据“有序、是否重复、是否需要键”选择数据结构
2. 掌握列表的增删改查、切片和排序
3. 理解元组不可变及解包
4. 掌握字典的键值操作和嵌套读取
5. 掌握集合的去重及交、并、差运算
【本课刻意不使用】
for、while 和推导式;它们会在 1.4 正式学习。
【本课成果】
能用合适的数据结构组织一份课程与学员信息。
【运行准备与参考】
只需 Python 3.10+,无需第三方库。
官方教程(数据结构): https://docs.python.org/zh-cn/3/tutorial/datastructures.html
"""
# ============================================================
# 第一部分:为什么不能只用很多普通变量
# ============================================================
student_1 = "小王"
student_2 = "小李"
student_3 = "小张"
# 三个人还可以分别命名;三百个人就会难以管理。
# 容器把一组相关值放在一起,后续可以统一查找、修改和遍历。
# 先记住选择原则:
# list:有顺序,内容会变化,可以重复。
# tuple:有顺序,创建后不应变化,可以重复。
# dict:通过“名字/编号”等键查找对应值。
# set:只关心有哪些不同的值,不关心顺序和重复次数。
# ============================================================
# 第二部分:列表 list
# ============================================================
students = ["小王", "小李", "小张"]
print(type(students)) # <class 'list'>
print(len(students)) # 3
print(students[0]) # 小王
print(students[-1]) # 小张
print(students[0:2]) # ['小王', '小李']
print("小李" in students) # True
# 下标从 0 开始。长度为 3 的列表,有效下标是 0、1、2。
# 访问 students[3] 会产生 IndexError。
# ----- 增加元素 -----
students.append("小赵") # 在末尾增加一个值
students.insert(1, "小周") # 在指定下标前插入
students.extend(["小钱", "小孙"]) # 追加另一个列表中的多个值
print(students)
# append 和 extend 不同:
demo_append = [1, 2]
demo_append.append([3, 4])
print(demo_append) # [1, 2, [3, 4]],把整个列表当成一个元素
demo_extend = [1, 2]
demo_extend.extend([3, 4])
print(demo_extend) # [1, 2, 3, 4],逐个追加
# ----- 修改元素 -----
students[0] = "小王同学"
print(students[0])
# 列表是“可变对象”:创建后可以直接修改其中的元素。
# ----- 删除元素 -----
students.remove("小周") # 按值删除第一个匹配项;不存在会 ValueError
last_student = students.pop() # 删除并返回最后一项
del students[0] # 按下标删除
print(last_student)
print(students)
# 如果不确定值是否存在,可以先用 in 判断;1.4 会把判断写进 if。
# ----- 查找、计数和排序 -----
numbers = [4, 2, 4, 1, 3]
print(numbers.index(4)) # 0,第一个 4 的下标
print(numbers.count(4)) # 2,共出现两次
ascending = sorted(numbers) # 返回新列表,不改变原列表
descending = sorted(numbers, reverse=True)
print(ascending) # [1, 2, 3, 4, 4]
print(descending) # [4, 4, 3, 2, 1]
print(numbers) # 原列表仍是 [4, 2, 4, 1, 3]
numbers.sort() # 原地排序,直接改变 numbers
print(numbers)
# sorted(...) 有返回值;list.sort() 修改原列表并返回 None。
# ----- 引用与浅复制的第一印象 -----
original = ["A", "B"]
same_list = original
same_list.append("C")
print(original) # ['A', 'B', 'C'],两个变量指向同一列表
original = ["A", "B"]
copied = original.copy()
copied.append("C")
print(original) # ['A', 'B'],外层列表已经分开
print(copied) # ['A', 'B', 'C']
# 现在只需理解“赋值可能共享同一个可变对象”。深浅拷贝会在 6.4 复习。
# ============================================================
# 第三部分:元组 tuple
# ============================================================
screen_size = (1920, 1080)
print(screen_size[0]) # 1920
print(screen_size[-1]) # 1080
# 元组与列表一样有顺序、能用下标,但元组不可变。
# screen_size[0] = 1280 会产生 TypeError。
width, height = screen_size # 解包:按顺序分别赋值
print(width)
print(height)
# 交换两个变量也使用解包。
left = "左"
right = "右"
left, right = right, left
print(left, right) # 右 左
# 单元素元组必须保留逗号。
one_item_tuple = (5,)
not_a_tuple = (5)
print(type(one_item_tuple)) # tuple
print(type(not_a_tuple)) # int
# 适合元组的例子:坐标、RGB 颜色、不会修改的固定配置。
# ============================================================
# 第四部分:字典 dict
# ============================================================
# 字典由“键: 值”组成。键像字段名,值是对应的数据。
student = {
"name": "小李",
"age": 20,
"city": "杭州",
}
print(student["name"]) # 小李
print(student.get("age")) # 20
print(student.get("email")) # None
print(student.get("email", "未填写")) # 未填写
# [] 和 get 的区别:
# student["missing"] 键不存在时产生 KeyError。
# student.get("missing") 键不存在时返回 None 或给定默认值。
# 增加和修改使用同一种写法。
student["email"] = "li@example.com" # 新键:增加
student["age"] = 21 # 已有键:修改
# 删除。
removed_city = student.pop("city")
print(removed_city)
print(student)
# 判断默认检查“键”是否存在。
print("name" in student) # True
print("小李" in student) # False,不会检查值
print("小李" in student.values()) # True
# keys、values、items 分别提供键、值、键值对。
print(list(student.keys()))
print(list(student.values()))
print(list(student.items()))
# 嵌套结构:字典中可以保存列表,列表中也可以保存字典。
course = {
"name": "Python 入门",
"lessons": ["变量", "数据结构", "流程控制"],
"teacher": {"name": "Alice", "city": "上海"},
}
print(course["lessons"][0]) # 变量
print(course["teacher"]["name"]) # Alice
# 读嵌套数据时从左向右:
# course["teacher"] 先得到内部字典;再 ["name"] 得到名字。
# 字典键必须是不可变、可哈希的类型,常见的是 str、int、tuple。
# list 不能作为键;目前把字段名写成字符串即可。
# ============================================================
# 第五部分:集合 set
# ============================================================
names = ["小王", "小李", "小王", "小张"]
unique_names = set(names)
print(unique_names) # 顺序不保证,元素只保留一份
print(len(unique_names)) # 3
# 空集合必须写 set()。{} 表示空字典。
empty_set = set()
empty_dict = {}
print(type(empty_set))
print(type(empty_dict))
skills = {"Python", "Git"}
skills.add("SQL")
skills.add("Python") # 已存在,不会重复增加
skills.discard("Java") # 不存在也不报错
print(skills)
# 集合没有稳定顺序,不能使用 skills[0]。
backend_skills = {"Python", "Git", "SQL"}
agent_skills = {"Python", "Prompt", "RAG"}
print(backend_skills & agent_skills) # 交集:双方都有
print(backend_skills | agent_skills) # 并集:所有不同技能
print(backend_skills - agent_skills) # 差集:只在左边
print(backend_skills ^ agent_skills) # 对称差:只属于一方
# ============================================================
# 第六部分:选择数据结构
# ============================================================
#
# “按顺序保存学习章节” -> list
# “保存固定坐标” -> tuple
# “通过学号查学生信息” -> dict
# “统计出现过哪些不同标签” -> set
#
# 不要为了“高级”选择复杂结构,要根据数据特征选择。
# ============================================================
# 本课检查清单
# ============================================================
#
# [ ] 会对列表进行增删改查
# [ ] 能说明 append 与 extend、sorted 与 sort 的区别
# [ ] 理解列表可变、元组不可变
# [ ] 会读取和修改字典及嵌套数据
# [ ] 会用集合去重并计算交、并、差
# [ ] 能根据场景选择 list、tuple、dict 或 set
# 课后练习:exercises/1_3_data_structures.py