列表与字典
这是什么:列表(list) = 按顺序排好队的一串值,用 [] 装;字典(dict) = 一组「键 → 值」的对应关系,用 {} 装。
为什么用:到目前为止,一个变量只能装一个值。要记全班 40 个成绩,难道起 40 个名字?有了列表和字典,一个变量就装得下一整车数据。
如何用:本章用 fruits 列表练增删改查和切片,再用一个「商品 → 价格」的字典练取值和遍历。
列表:排好队的一组值
方括号把值排成一队,逗号隔开,增删改查都方便:
fruits = ["苹果", "香蕉", "橘子"]
fruits.append("葡萄") # 增:加到队尾
fruits[0] = "红苹果" # 改:按位置替换
del fruits[1] # 删:删掉"香蕉"
print(fruits) # 查:整个列表
print(fruits[-1]) # -1 表示最后一个
print(fruits[1:3]) # 切片:取第 1 到第 2 个(不含 3)
print(len(fruits)) # 一共几个
你会看到:
['红苹果', '橘子', '葡萄']
葡萄
['橘子', '葡萄']
3
重点:位置从 0 开始数,fruits[0] 才是第一个——这是新手第二大坑(第一大还是中文引号)。切片和 range 一样含头不含尾。
挨个处理叫遍历,for 循环一步到位:
fruits = ["红苹果", "橘子", "葡萄"]
for f in fruits:
print("今天吃", f)
你会看到:
今天吃 红苹果
今天吃 橘子
今天吃 葡萄
字典:按名字找值
列表靠位置找值,字典靠键(key)找值——真像查字典:按"字"翻到"释义":
frog = {"名字": "小绿", "年龄": 3, "会游泳": True}
frog["爱好"] = "吃虫子" # 增:键不存在,就是新增
frog["年龄"] = 4 # 改:键已存在,就是覆盖
del frog["会游泳"] # 删:连键带值一起删
print(frog["名字"]) # 查:按键取值
for key, value in frog.items():
print(key, "→", value)
你会看到:
小绿
名字 → 小绿
年龄 → 4
爱好 → 吃虫子
注意:查一个不存在的键(比如 frog["体重"])会直接报 KeyError。拿不准就先问一句:if "体重" in frog:。
何时用哪个
| 场景 | 用什么 |
|---|---|
| 一组有顺序的同类东西:成绩单、待办清单 | 列表 [] |
| 描述一件事的多条属性:一只蛙的名字、年龄、爱好 | 字典 {} |
| 要按位置取值("第 3 个") | 列表 |
| 要按名字取值("年龄是多少") | 字典 |
记忆口诀
列表按号排队,字典点名签到;位置从 0 起,切片含头不含尾。
⚠️ 新手翻车现场
翻车一:索引越界
fruits = ["苹果", "香蕉", "橘子"]
print(fruits[3])
IndexError: list index out of range
逐行分析:第 1 行登记了 3 个元素,没问题;第 2 行出事——你心里想的是"取第 3 个",但列表位置从 0 起数,3 个元素的位置只有 0、1、2,fruits[3] 实际是"第 4 个",一伸手就伸进了空处。Python 怎么发现的?取值那一刻它会先核对下标是否在 0~2 的范围内,越界就抛 IndexError: list index out of range(下标越界)。好消息:这类错报得快、指得准,顺着报错行就能定位。
修复:想取"第 3 个"写 fruits[2];想取最后一个,无脑用 fruits[-1]——负数从队尾倒数,永远不会越界。举一反三:见到 IndexError,先 print(len(列表)) 数一数,再看下标是不是超了。
翻车二:把 append 的返回值装回列表
fruits = ["苹果"]
fruits = fruits.append("香蕉")
print(fruits)
None
逐行分析:第 1 行没问题;第 2 行是事故现场,坑在开头的 fruits =——后半句其实已经把"香蕉"装进列表了,append 干完活顺手返回一个 None(意思是"我没有返回值"),而你用 fruits = 把这个 None 覆盖装回了盒子,列表从此"失联"。Python 为什么不报错?赋值本来就是合法操作,它猜不到你是想保留列表——又一个"不报错却坏事"的逻辑 bug,直到第 3 行 print 把 None 亮出来才露馅。
修复:删掉 fruits =,单写一行 fruits.append("香蕉")。举一反三:列表的 append、sort、reverse 都是"原地动手、不还东西"的脾气,一律别拿它们的返回值去赋值。
翻车三:查了字典里没有的键
frog = {"名字": "小绿"}
print(frog["体重"])
KeyError: '体重'
逐行分析:第 2 行想按"体重"这个键取值,可字典里只登记过"名字",Python 沿着键找了一圈没找到,报 KeyError: '体重'——冒号后面就是那个找不到的键,指名道姓。注意:语法完全合法,Python 无法提前知道你会查什么键,所以它是运行到这一行才发现的。
修复两选一:确定键存在再查;拿不准就先用 if "体重" in frog: 探一句,或者用 frog.get("体重")——查不到时返回 None 而不是报错(先记个名字,以后常用)。
📦 完整小示例
用字典记三门课成绩,顺手算总分和平均分,存成 scores.py:
scores = {"语文": 92, "数学": 87, "英语": 95}
total = 0
for subject, score in scores.items():
print(f"{subject}:{score} 分")
total += score
print(f"总分:{total}")
print(f"平均分:{total / len(scores)}")
你会看到:
语文:92 分
数学:87 分
英语:95 分
总分:274
平均分:91.33333333333333
逐段中文精讲
- 第 1 行(数据登记):字典把"科目 → 分数"一一配对登记。用字典而不是列表,是因为取数时你想按名字拿("数学多少分"),而不是按位置猜("第 2 个是什么")。
- 第 2 行(累加器清零):
total = 0放循环外,理由和上一章的计数器一样:只需要归零一次,写进循环里每轮都被清空。 - 第 3 行(空行)与第 4 行(遍历字典):登记完数据空一行再开工;
scores.items()把字典拆成一对对(键, 值),for subject, score in ...每轮同时接过一个键和一个值——这是字典遍历的标准姿势,一次拿两个。 - 第 5~6 行(边遍历边干活):先打印本科目成绩(f-string 填坑),再
total += score往存钱罐里加一笔,三科的分数就这样被"顺路"加总了。 - 第 8 行(总分落袋):写在循环外,此刻三笔已加完,274 分出账。
- 第 9 行(平均分):
total / len(scores)——len()数字典里有几个键(3 个),总分除以科数得平均。打印出的91.33333333333333拖着长尾巴,就是变量那章 Q4 说的浮点精度现象,学了格式化输出再收拾它。
这个例子是"字典 + 遍历 + 累加器"的经典组合:真实项目里统计订单总额、汇总考试得分,骨架就是这样。
🎯 什么时候用它
- 购物车与清单:商品列表、待办事项、播放队列——有顺序、会增删的数据,天然是列表的主场:
append加货、del移除、切片取一段。 - 描述一个对象的属性:用户资料(姓名/城市/头像地址)、一件商品的详情、一份配置——"按名字取信息"的数据,用字典最顺手。
- 读懂真实世界的数据:网页接口、小程序后端返回的数据(JSON),拆开看全是"列表套字典、字典套列表"——学透这两位,你就看懂了互联网数据的样子。
动手改
- 建一个列表装 5 个你喜欢的数字,打印最大值和最小值(提示:
max()和min()) - 建一个字典存朋友的姓名、城市、爱好,新增一个键、再删掉一个键,每一步打印整个字典看变化
- 对列表
[3, 1, 4, 1, 5]用切片取出第 2 到第 4 个数,并打印它的长度
下一章:函数,把代码打包成随叫随到的工具 🐸