列表 — 主力数据结构,和它被滥用的方式
列表 — 主力数据结构,和它被滥用的方式
这一章讲 list:Python 里最重要的数据结构。 但原书的讲法有个鲜明的特点—— 每教一个操作,作者都同时告诉你什么时候不该用它:不该按下标取元素、不该切片、 不该在列表里混装不同类型的东西。读完你会拿到一套「列表使用哲学」,而不只是方法清单。
1. 这一章讲什么
原书开宗明义:列表(在其他语言里叫别的名字)是软件开发的驮马(workhorse)—— 它让你把多个对象存进一个变量,这「可能是最重要的数据结构」。[^1]
本章的隐含主线问题:一个列表装的是什么,决定了你对它能做什么、该做什么。 如果列表装的是「一组性质相同的对象」,那么遍历整个列表、对每个元素做同一件事,就是唯一健康的用法; 任何「挑其中一个出来特殊对待」的代码,都是信号:要么数据放错了容器,要么结构该改。
2. 顶层全景:列表的一生
创建 使用 收束
[] 遍历(for x in xs) 排序(sort/sorted)
[a, b] 变换(列表推导式) 合并(+、append、zip)
.append() 取元素(作者反对 [])
切片(作者反对 [1:3])
图说:上半行是作者推荐的,下半行是「能但不该」——本章的篇幅分配也是这个比例。主线例子用到底:一份水果清单 ["apple", "pear", "banana"],每一步操作都落在它身上。[^2]
3. 核心原理
3.1 创建与填充:append 与 pop
解决什么问题: 手头有一组同类对象,要一个容器按先来后到存着。
怎么做:
empty_list = [] # 空列表
empty_list.append("hello") # 末尾加一个 → ['hello']
my_list = ["hello", "world"] # 或直接初始化
my_list.pop() # 删末尾并返回它 → 返回 'world',列表变回 ['hello']append 和 pop 是一对:一个从末尾加,一个从末尾删并取出(这种后进先出的用法,
就是数据结构课里的「栈」;书里没点名,知道这个对应即可)。列表能装多少元素,只受内存限制。[^3]
一个立刻要立的规矩:别在列表里混装类型。 ["Apple", 5] 合法,但「你会很难找到这个对象的名字——
这就是数据结构有缺陷的明显信号」。不同类型属性的组合,该用类(第 11 章),不该塞进一个列表。[^4]
3.2 列表推导式:一行造列表
解决什么问题: 「对 0 到 4 的每个数算平方,收集成列表」这种变换,用循环写要四五行,还有临时变量。
怎么做: Python 的招牌语法——列表推导式(list comprehension):
[i**2 for i in range(5)]
# [0, 1, 4, 9, 16]走一遍: range(5) 依次给出 0–4,每个存进 i;i**2 算出平方;所有结果收集成一个新列表。[^5]
它还能带过滤器——只留满足条件的:
fruits = ["apple", "pear", "banana"]
[fruit for fruit in fruits if fruit != "pear"] # ['apple', 'banana']
[i for i in range(10) if i % 2 == 0] # [0, 2, 4, 6, 8] 偶数为什么有效、边界在哪: 它把「遍历 + 变换 + 收集」压成一句,消掉了临时变量(还记得第 02 章吗: 变量越少,读者要记的东西越少)。但作者立刻警告:它能写得非常紧凑,也能写得非常难读—— 书里给了一个「过长」的反面例子(一行里挤进遍历、替换、去空格、两个条件),结论是: 「代码长一点但可读,永远好过短而难懂。」推导式超过「一个变换 + 一个条件」就该拆成普通循环。[^6]
3.3 遍历:首选 for x in xs
解决什么问题: 对列表每个元素做同一件事。
怎么做: 主线例子走一遍:[^2]
fruits = ["apple", "pear", "banana"]
for fruit in fruits:
print(fruit)
# apple / pear / bananafor fruit in fruits 一次取一个元素进 fruit——不需要下标、不需要长度、空列表时自然什么都不做。
作者贴心地备注:编程里不讲究英文语法,fruits 存一堆 fruit,复数对单数,够用就好(可读性优先于语法正确)。[^7]
需要下标时,用 enumerate,不要自己数:
for i, fruit in enumerate(fruits):
print(i, fruit)
# 0 apple / 1 pear / 2 bananaenumerate 一边遍历一边给出序号(从 0 开始)。对比「不推荐」的写法
for i in range(len(fruits)): print(fruits[i])——书里把这种下标循环称为「iterator」用法(这其实是书里的误称,Python 的 iterator 另有所指;这里就当它说「下标迭代」),
评价是「混乱且易错,最好别用」。[^8]
为什么有效: 下标是间接层——你要的不是数字 i,是第 i 个元素;多一层间接,就多一层写错的空间
(差一位、越界,都是经典 bug)。for x in xs 把这层间接删了。书里配了一段 C++ 旧式写法的对照
(手动下标、以及更糟的 iterator 类型),说明「这种访问方式曾经到处都用,幸好已经过去了」。[^9]
3.4 按下标取元素与切片:能不用就不用
解决什么问题: 偶尔你确实需要「第几个」或「中间一段」。
怎么做(以及作者的反对票):
fruits[1] = "orange" # 改第二个元素 → ['apple', 'orange', 'banana']
numbers = [1, 2, 3, 4, 5]
numbers[1:3] # 切片:取索引 1 到 3 之前 → [2, 3]作者对这两个操作的立场是本章最强的:「别用 [] 运算符。 如果你非要用,说明你的代码很可能有缺陷,该修。」 理由是第 1 节的哲学:按下标取一个元素,等于「从列表里随机挑一个特殊对待」—— 这违背「所有元素一视同仁」,而违背它的代码,测试要逐个情况覆盖,复杂度失控。[^10]
切片(slicing,[1:3] 这种取一段)同样「看起来酷,但应该少用;它是代码不够优的信号」。
如果非用不可,作者的条件是:配足单元测试,防差一位错误。[^11]
切片的几个技巧,书里承认「有用」但我们按作者口径只作了解:负数从尾部数([-1] 是最后一个)、
缺省首尾([:-1] 去掉最后一个)、第三个参数跳步([::2] 隔一个取一个)、[::-1] 整个倒序——
顺带的彩蛋是用 word == word[::-1] 判断回文(正读反读相同的词,如 anna)。[^12]
判断(我们的,不是书里的): 「禁用下标」作为铁律太硬,但作为默认很对。 数据处理里
xs[0]取第一个、解包失败时兜底,都是正当用法;真正该删的是裸数字下标满地跑的代码 (每出现一个xs[3],读者都要回去数第四位是什么)。判据:下标是不是「有名字的常量」 (比如FIRST = 0),不是就该重构。 如果错,会错在: 数值算法(本章的矩阵、第 18 章的数值积分)本质上就是在跟下标打交道; 那一类代码按下标工作是本职,「禁用」不适用——作者自己在矩阵例子里也用了matrix[0][1]。
3.5 嵌套列表与矩阵
列表里装列表,就是二维结构——矩阵(matrix,排成行和列的数表):
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
matrix[0] # [1, 2, 3] —— 第一行
matrix[0][1] # 2 —— 第一行第二个
[row[0] for row in matrix] # [1, 4, 7] —— 每行第一个,推导式直接做列切片作者对嵌套的意见跟对切片一致:维度一多就乱,矩阵运算请交给 NumPy(第 09 章)—— 「出于性能原因强烈建议」。嵌套的列表推导式能快速变成天书,书里的替代是拆成普通循环写。[^13]
3.6 排序:sort 还是 sorted,这是个契约问题
解决什么问题: 把列表按大小排好。
怎么做:
a = [3, 1, 2]
a.sort() # 就地改:a 变成 [1, 2, 3]
a_sorted = sorted(a) # 不动原列表,返回一个排好的新列表
a.sort(reverse=True) # 降序区别表面很小,选择上作者明确站 sorted:「它给我一个新列表、一个新名字。」
回想第 02、03 章:不复用变量、不让数据在你看不见的地方被改——sort 正好违反这两条,
只有「你就是故意要改原列表」时才用它。[^14]
附带两个彩蛋:sorted 不限于列表——字符串、dict 都能排,总是返回列表
(sorted("hello") → ['e','h','l','l','o'];对 dict 排的是它的键)。[^15]
3.7 合并:加号、逐个 append、zip
怎么做:
a = [1, 2, 3]; b = [4, 5, 6]
a + b # [1,2,3,4,5,6] —— 造一个新列表
for element in b: a.append(element) # 把 b 的元素逐个人肉搬进 a
list(zip(a, b)) # [(1,4),(2,5),(3,6)] —— 两两配对成 tuple 列表zip 把两个列表的对应位置配成一对,返回可转成列表的 zip 对象。
但作者的警告照旧:「合并列表的时候,你多半该停下来想想——危险在于合并出一个元素不同质的列表。
不同的东西,保持分开。」[^16]
3.8 字符串是「只读的列表」:一个跨章节的桥
书里插了一个对照框:字符串大致就是一个字符的列表,所以列表的操作它很多都有——
for letter in "Hello" 可以逐个字符遍历,"Hello"[1] 能取下标。[^13b]
关键差别在第 03 章已经立过:字符串不可变,word[1] = "a" 直接报
TypeError: 'str' object does not support item assignment——想「改」某个字符,只能造新字符串。[^13c]
这个对应关系值钱的地方在于:学完列表,字符串的大部分直觉你已经有了; 第 05 章讲字符串时,可以直接从「它和列表的异同」切入,不用从零学。
3.9 学不完的 API 怎么办
本章最后,作者对「列表有几百个函数,学不完」给了全书方法论的一句总结: 读文档是老派做法;更实用的是用 Google 搜「我想对列表做什么」,练会 Python 的词汇; 再现代一点,问 AI 工具——「它们能帮到你,但小心,它们也会把你带偏。」 唯一不可替代的是:自己动手练。[^17]
4. 书里还有那些操作:逐个走一遍
第 3 节按「哲学」组织,这一节把书里的操作示例逐个走一遍——每段代码旁边都有具体的数, 方便你在 REPL 里照着敲。
4.1 切片四技巧,各配一个具体输入
主线例子换数字列表 [1, 2, 3, 4, 5],四个技巧各走一遍:[^12]
list = [1, 2, 3, 4, 5]
list[1:3] # [2, 3] —— 基本款:取索引 1 到 3 之前
list[-2:] # [4, 5] —— 负数从尾部数:-2 是倒数第二个
list[:-1] # [1, 2, 3, 4] —— 起止可以省略:不写起点 = 从头,不写终点 = 到尾
list[::2] # [1, 3, 5] —— 第三个参数是步长:每隔一个取一个
list[::-1] # [5, 4, 3, 2, 1] —— 负步长 = 倒着走:整个翻转边界规则一句话:左闭右开——[1:3] 含索引 1、不含索引 3,所以得 [2, 3]。
这条规则造成的「差一位」错误,正是作者要求切片配测试的原因。[^11]
回文判断是作者唯一主动夸过的切片用法:
word = "anna"
word == word[::-1] # True —— 正读和反读相同「这段代码看着确实酷。但老实说,你该尽量少用切片——它是坏代码的信号。」作者的原话里, 夸和贬隔着一行,这就是他全章的基调。[^12]
4.2 多维列表:一个矩阵的完整一生
书里给了一个 3×3 矩阵的完整操作链,走一遍:[^13]
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix[0] # [1, 2, 3] —— 第一个元素是一整行(一个列表)
matrix[0][1] # 2 —— 第一行的第二个:先取行,再取列,两层 []
# 排成方阵的样子写,更易读(Python 不在乎,人在乎):
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
# 列表推导式直接做「取每行第一个」的列操作:
[row[0] for row in matrix] # [1, 4, 7]三层嵌套的推导式书里也演示了,但随即给出两个更平的替代(普通循环版),结论一样: 「能读性优先,嵌套推导式很快变得令人困惑。」[^13]
一个警告顺带记下:各行列数不同(参差不齐的矩阵)「大概率说明你的代码哪里怪,该重想」—— 方阵之外的结构,通常该用别的东西(第 09 章的 NumPy 或第 11 章的类)。
4.3 排序与合并的输出,逐个对账
a = [3, 1, 2]
a.sort(); a # [1, 2, 3] —— 就地改
a.sort(reverse=True); a # [3, 2, 1] —— 降序
b = [3, 1, 2]
b_sorted = sorted(b)
b # [3, 1, 2] —— 原列表没动
b_sorted # [1, 2, 3] —— 新列表sorted 还能排别的东西,书里给了两个彩蛋:对字符串返回字符列表 sorted("hello") → ['e','h','l','l','o'];
对 dict 返回排好序的键列表 sorted({1:"2", 4:"5", 3:"11"}) → [1, 3, 4]。[^15]
合并的三种写法,输出相同、形状不同:[^16]
a = [1, 2, 3]; b = [4, 5, 6]
a + b # [1,2,3,4,5,6] —— 新列表
for element in b: a.append(element) # a 自己变长
list(zip(a, b)) # [(1,4),(2,5),(3,6)] —— 配对成 tuplezip 的要点:它返回的不是列表,是一个「配对迭代器」,要 list(...) 包一层才看得见内容;
配对在短列表结束处停止(长度不等时,多余的被丢掉——这是补充,书里没强调)。
4.4 enumerate 与「i 的没落」
fruits = ["apple", "pear", "banana"]
for (i, fruit) in enumerate(fruits): # 括号可省:for i, fruit in ...
print(i, fruit)
# 0 apple / 1 pear / 2 banana对比作者不推荐的下标版 for i in range(len(fruits)): print(i, fruits[i]):
两条代码的输出一模一样,但下标版多了一层「先取数字、再拿数字换元素」的间接——
i 有机会越界、有机会差一位,而 enumerate 版没有这个机会。
书里的历史注脚:C++ 当年连下标都嫌高级,还有更糟的手写 iterator 写法(类型名长到一行的那种),
「幸好那些日子过去了」。[^9]
4.5 本章的三个加框小注,一并收拢
原书在列表一节插了三个加框,各占一行话:
- Old-School Arrays:C++ 当年用
new/delete手工申请释放内存,「非常脆弱、极易出错」; 如今连 C++ 都有了接近 Python 列表的 vector——手工内存管理的年代「一去不复返了」。[^18] - English Grammar in Programming:
for fruit in fruits里 fruit/fruits 单复数对不上语法没关系—— 编程的目标是代码好懂,语法正确性优先级很低。(for person in people这种对不上的,照写。)[^7] - Strings vs. Lists:字符串近似「只读的字符列表」,遍历、下标都通,唯独不能改单个字符
word[1] = "a"→TypeError: 'str' object does not support item assignment。[^13c]
三个框合起来是一句话:列表的直觉大量可迁移,但「可变性」这条界线不可迁移。
4.6 「别用 []」的正面教材:什么时候遍历是对的
回到第 3.3 节的哲学,给它配一个完整对比例子。[^10]
fruits = ["apple", "pear", "banana"]
for fruit in fruits: # 每个元素都被同样对待
print(fruit)
# apple / pear / banana这段代码里没有任何下标——因为没有元素需要被特殊对待。
而一旦写下 fruits[1] = "orange",你就是在说:「第二个元素和其他的不一样,我要亲手动它。」
作者的判断:这行代码本身就说明数据结构有问题——
「这段代码违背了『列表所有元素应被一视同仁』的原则——你只是从列表里随机挑了一个。 所以你应该一般性地避免 [] 运算符。如果非用不可,你的代码很可能有缺陷,该修。」[^10]
修的方向在上一章已经给过:要么换容器(不同属性的组合该进 dict 或类),要么换数据形状 (让元素们重新变得同质),而不是给下标操作配更多注释。
4.7 列表推导式的过滤器,两个完整走查
第 3.2 节给了语法,这里把书里的两个例子走到底。[^6]
走查一:从水果清单里剔除梨。
fruits = ["apple", "pear", "banana"]
no_pear = [fruit for fruit in fruits if fruit != "pear"]
# 拆开读:for 把 fruits 里的元素依次放进 fruit;
# if 检查「fruit 不是 pear」,通过的才留下;
# 留下的 fruit 收集成新列表
no_pear # ["apple", "banana"]走查二:0 到 9 里的偶数。条件 i % 2 == 0 用取余:i 除以 2 的余数为 0 就是偶数(第 03 章的 ///% 在此复用)。
[i for i in range(10) if i % 2 == 0] # [0, 2, 4, 6, 8]
[i**2 for i in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] —— 不带过滤的平方版书里的「过长反面例」值得原样看一眼,建立尺度感:
files = [file.stem.replace(" ", " ").strip() for file in
p.iterdir() if file.is_file() and file.suffix is ".py"]一行里塞了:遍历目录、替换、去空格、两个条件。「这样的推导式能写,但不该写—— 宁可长一点、可读,不要短而难懂。」[^6]
4.8 「学不完」的正确姿势
原章末尾的那张方法论,展开成可执行的三步:
- 先练词汇,再查文档。 「对列表做 X」的 X 用 Python 的哪个词说?append、slice、filter…… 词汇来自亲手敲,不来自阅读。
- 搜索优先于文档。 文档是全集,问题是个子集;带着「我想做什么」去搜,命中率远高于翻目录。 「这需要练,但值得。」[^17]
- AI 工具可用但要验。 「它们能帮你,也会带你走偏」——带偏的方式是给出看似合理但跑不起来的代码, 对策只有一个:任何 AI 给的代码,自己跑一遍再信(这也是第 01 章「测试是唯一检查」的日常版)。
4.9 创建与填充,从空列表到成品
把第 3.1 节的 API 扩成一次完整的「制造过程」:[^3]
empty_list = []
empty_list # [] —— 空列表本身没啥用,但它是起点
empty_list.append("hello")
empty_list # ["hello"] —— 加了一个
my_list = ["hello", "world"] # 或者直接初始化:方括号 + 逗号分隔
my_list # ["hello", "world"]
my_list.pop() # 返回 "world",my_list 变回 ["hello"]pop 的完整语义:删除末尾元素并把它还给你。所以 my_list.pop() 单独一行时,
元素被删了但没人接,白拿了——通常写作 last = my_list.pop(),既删了末尾又拿到了值。
append/pop 这一对配合,就是数据结构课里「栈」(后进先出)的完整实现,
只是 Python 没给它起这个名字。[^3]
再补一个「混装反例」的正面对照。书里用 ["Apple", 5] 展示混装有多难命名——
试试给它起个名字:fruit_and_count?item?怎么起都别扭。
而同质列表起名毫不费力:fruits、prices、ages——一个名字起得顺不顺,就是数据结构对不对的试纸。[^4]
4.10 嵌套推导式的三个版本,复杂度肉眼可见
书里用一道题对比了三个版本:造一个「每行长度递增」的锯齿二维列表 [[], [0]], [[0], [0, 0]], [[0, 0], [0, 0, 0]]。[^13]
# 版本一:双层列表推导式(一行,但 reader 哭了)
[[[0] * (i + j) for i in range(2)] for j in range(3)]
# 版本二:外层循环 + 内层推导式(推荐)
matrix = []
for j in range(3):
sub_list = [[0] * (i + j) for i in range(2)]
matrix.append(sub_list)
# 版本三:全循环(最直白)
matrix = []
for j in range(3):
sub_list = []
for i in range(2):
sub_list.append([0] * (i + j))
matrix.append(sub_list)三个版本输出相同;作者的裁决:版本二最好——「简单的列表推导式是这个 case 的最佳解」。 判据和前面一脉相承:推导式的合法长度,以「读的人不皱眉」为界。
4.11 「数字母」式直觉:列表是序列的通用形态
把本章收在一个更大的图景上:字符串、tuple、range、文件逐行——它们都不是列表,但都能被 for x in xs 遍历、被 sorted 排序、被 in 查询。
列表是这种「序列」形态里唯一可变的、最通用的一个;学会它,等于同时学会半个 Python 的数据面。
这也是为什么作者把列表放在所有数据结构最前面讲:它不是「四选一」之一,是其他几个的参照物。
4.12 主线例子,最后一次完整回放
把全章的操作串在同一份数据上,一次看完:
fruits = ["apple", "pear", "banana"]
│
├─ 遍历 for fruit in fruits: → 每个元素被同样对待
├─ 带序号 enumerate(fruits) → (0,"apple") (1,"pear") (2,"banana")
├─ 变换 [f.upper() for f in fruits] → ["APPLE","PEAR","BANANA"](变换规则为你所写)
├─ 过滤 [f for f in fruits if f != "pear"] → ["apple","banana"]
├─ 排序 sorted(fruits) → ["apple","banana","pear"] 新列表
└─ 配对 list(zip(fruits, [3,2,5])) → [("apple",3),("pear",2),("banana",5)]
图说:主线例子到此走完;从创建到输出的每一步,全章没有一个 [] 下标。
(upper() 把字符串转成全大写,是第 05 章字符串操作的预告;zip 的配对在短列表结束处停止。)
这份回放同时是本章的「自测题」:遮住右列,只看左列的操作名,能写出输出形状(不必精确到值),
说明本章已经读透;写不出的那一行,回到对应小节重走一遍例子即可。
最后交代一句本章的边界:列表能装的元素数量只受内存限制——书里明说「上限就是你计算机的内存空间」,这不是修辞,是机制:列表是动态数组,不够就自动扩,扩到操作系统不肯给为止。这也是为什么「列表里塞什么」比「列表能塞多少」重要得多——容量永远不是瓶颈,元素不同质才是。
### 4.13 与 NumPy 的分工预告
本章所有「二维以上」的例子,作者在正文里都指向了同一个出口:**矩阵运算请交给 NumPy**。
理由在第 09 章展开(性能),这里先记住分工边界——纯 Python 的嵌套列表适合「装结构」
(棋盘、表格、树的孩子列表,第 19 章的渗流模拟就是),不适合「算数值」。
一到乘法、求逆、滤波这类数值动作,就换 NumPy 的数组——那是它的主场,而且快上几个数量级。
## 5. 作者的判断与证据
**书里给了证据的:** 每个操作的代码示例和输出都可直接运行;`enumerate` 与下标循环的对照、
`sort` 与 `sorted` 的对照,都是「跑一次就明白」的演示。[^8][^14]
**作者的判断(立场性主张):**
- 「别用 []、少用切片」——立场最强的部分;他的依据是「特殊对待 = 复杂度」,逻辑自洽,但如我们的判断块所说,数值代码里要放松;
- 「列表里只装同类对象」——判断+经验,普遍认同;
- 「AI 工具会带你偏」的提醒——2026 年的朴素说法,我们补充:这不是 Python 的问题,是概率性生成工具的固有属性。
## 6. 边界与局限
- 本章没讲 **insert/remove/index 等常用方法**,也没讲 `del`——作者的方法论是「用到再查」,不是全表;
- 浅复制与深复制的区别在本章仍是隐含的(第 03 章提过 `copy()`);
- 生成器表达式、`map`/`filter` 没出现——书里认定列表推导式覆盖日常所需;
- 性能(Big-O)层面一句没提:list 尾部 append 快、中间插入慢这些,书里零涉及。
## 7. 可带走的
**本章主线例子,一行写完:** `fruits = ["apple", "pear", "banana"]` → `for fruit in fruits` 一视同仁遍历、
需要序号就 `enumerate`、要变换就 `[... for ... if ...]`、要排序用 `sorted` 拿新列表——
全程不碰下标。[^2]
1. **列表装同类对象**;混装类型是数据结构选错的信号,该用类。
2. **遍历首选 `for x in xs`**;需要序号用 `enumerate`,别用 `range(len(xs))`。
3. **下标和切片默认不用**;非用不可时配足测试。回文判断 `word == word[::-1]` 是少数作者也认的妙用。
4. **列表推导式 = 一个变换 + 一个过滤为限**;更长就拆成循环。
5. **`sorted` 优于 `sort`**(新列表 vs 暗中改原列表),除非你故意要改。
6. **合并前三思**:加号造新列表、zip 配对,但合并往往意味着该重新审视数据结构。
7. **矩阵交给 NumPy**,别用嵌套列表硬扛。
8. **API 学不完是正常的**:练会词汇 → 会搜 → 会问;但必须自己写。
再补一条书里夹在正文中的旧闻:作者在「Old-School Arrays」小框里顺带解释,数组(array)是 C++ 时代的概念,
那时要用 `new` 和 `delete` 手工申请和释放内存,「非常脆弱、极易出错」;如今连 C++ 都有了接近 Python 列表的 vector——
那套手工内存管理的年代,「一去不复返了」。[^18]
## 8. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 列表是驮马 | Lists | `text/13-fm-lists.txt:37`(搜「workhorses」) |
| 混装类型的警告 | Lists | `text/13-fm-lists.txt:47`(搜「Apple”, 5」) |
| append/pop | Lists | `text/13-fm-lists.txt:61`(搜「append(”hello”)」) · `text/13-fm-lists.txt:82`(搜「pop」) |
| 列表推导式与过滤器 | Lists | `text/13-fm-lists.txt:90`(搜「i**2 for i」) · `text/13-fm-lists.txt:101`(搜「no_pear」) |
| 过长的推导式反面例 | Lists | `text/13-fm-lists.txt:116`(搜「a little too long」) |
| for x in xs 遍历、语法备注 | Lists | `text/13-fm-lists.txt:126`(搜「for fruit in fruits」) · `text/13-fm-lists.txt:133`(搜「English Grammar」) |
| enumerate 与下标循环之贬 | Lists | `text/13-fm-lists.txt:144`(搜「enumerate」) · `text/13-fm-lists.txt:155`(搜「not as recommended」) |
| C++ 旧式迭代对照 | Lists | `text/13-fm-lists.txt:170`(搜「Old-School」) |
| 「别用 []」的主张 | Lists | `text/13-fm-lists.txt:193`(搜「use the [] operator」) |
| 切片与技巧、回文 | Lists | `text/13-fm-lists.txt:211`(搜「slicing」) · `text/13-fm-lists.txt:242`(搜「anna」) |
| 嵌套列表、NumPy 建议 | Lists | `text/13-fm-lists.txt:262`(搜「Multidimensional」) · `text/13-fm-lists.txt:272`(搜「highly advisable」) |
| sort / sorted 的选择 | Lists | `text/13-fm-lists.txt:327`(搜「ascending order」) · `text/13-fm-lists.txt:348`(搜「prefer sorted」) |
| 合并与 zip、合并警告 | Lists | `text/13-fm-lists.txt:361`(搜「Merging Lists」) · `text/13-fm-lists.txt:388`(搜「rethink」) |
| 「学会自己去查」方法论 | Strings(本章收尾段) | `text/14-fm-strings.txt:1`(搜「hundreds of functions」) |
[^1]: 出处:「Lists」第 37–40 段(`text/13-fm-lists.txt:37`,搜「workhorses」)。
[^2]: 出处:「Lists」第 125–131 段(`text/13-fm-lists.txt:126`,搜「for fruit in fruits」)。
[^3]: 出处:「Lists」第 56–85 段(`text/13-fm-lists.txt:61`,搜「append」;第 80 段,搜「pop」)。
[^4]: 出处:「Lists」第 43–55 段(`text/13-fm-lists.txt:49`,搜「avoid doing this」)。
[^5]: 出处:「Lists」第 87–96 段(`text/13-fm-lists.txt:88`,搜「list comprehension」)。
[^6]: 出处:「Lists」第 113–118 段(`text/13-fm-lists.txt:114`,搜「difficult to read」;第 116 段,搜「too long」)。
[^7]: 出处:「Lists」第 133–138 段(`text/13-fm-lists.txt:133`,搜「English Grammar」)。
[^8]: 出处:「Lists」第 142–167 段(`text/13-fm-lists.txt:144`,搜「enumerate」;第 165 段,搜「iterator is simply a number」)。
[^9]: 出处:「Lists」第 169–186 段(`text/13-fm-lists.txt:170`,搜「Old-School」)。
[^10]: 出处:「Lists」第 188–203 段(`text/13-fm-lists.txt:190`,搜「starts at 0」;第 199 段,搜「simply pick an element」)。
[^11]: 出处:「Lists」第 204–215 段(`text/13-fm-lists.txt:212`,搜「sign of suboptimal code」)。
[^12]: 出处:「Lists」第 216–248 段(`text/13-fm-lists.txt:218`,搜「-2」;第 242 段,搜「anna」)。
[^13]: 出处:「Lists」第 262–322 段(`text/13-fm-lists.txt:264`,搜「nested」;第 272 段,搜「NumPy」;第 302 段,搜「quickly becomes confusing」)。
[^14]: 出处:「Lists」第 324–350 段(`text/13-fm-lists.txt:348`,搜「prefer sorted」)。
[^15]: 出处:「Lists」第 351–359 段(`text/13-fm-lists.txt:353`,搜「sorted(”hello”)」)。
[^16]: 出处:「Lists」第 361–389 段(`text/13-fm-lists.txt:385`,搜「zip」;第 388 段,搜「rethink」)。
[^17]: 出处:「Strings」开头(`text/14-fm-strings.txt:1`,搜「hundreds of functions」;第 6 段,搜「practice by yourself」)。此段在文件中位于 Lists 章收尾处,内容是列表的延续讨论。
[^13b]: 出处:「Lists」第 251–255 段(`text/13-fm-lists.txt:252`,搜「list of characters」)。
[^13c]: 出处:「Lists」第 256–260 段(`text/13-fm-lists.txt:260`,搜「item assignment」)。报错原文:`TypeError: 'str' object does not support item assignment`——字符串不可变,想改只能造新串。
[^18]: 出处:「Lists」第 73–78 段(「Old-School Arrays」框,`text/13-fm-lists.txt:75`,搜「new and delete」;「those days are over」见第 77 段)。