一、为什么需要列表
前面学的变量,一次只能装一个值:一个分数、一个名字。但真实世界里,数据常常是一串的。
比如一个宿舍 5 个人的数学分数。最笨的写法,是起 5 个变量:
s1 = 88
s2 = 92
s3 = 75
s4 = 96
s5 = 81
分数一多,变量就多到管不过来。更好的办法:用一个列表,把这一串数装进一个名字里。
scores = [88, 92, 75, 96, 81]
print(scores)
输出:
[88, 92, 75, 96, 81]
一个变量 scores,就装下了 5 个分数。这种「一个变量装一串数」的容器,就是列表。
scores = [88, 92, 75, 96, 81]
print('一共', len(scores), '个分数')
print('最高分', max(scores))
输出:
一共 5 个分数
最高分 96
列表里每个位置上的数,叫一个元素。元素可以是数字、文字,甚至混着放。
课程思政|数据安全与法治素养 · 一份成绩单一份责任
列表解决的其实是个很朴素的问题:一串数怎么装。成绩单、名单、商品清单,一个变量就装下几十上百条。可这一串数背后往往是一个个具体的人,同学的分数、客户的电话,都是受保护的个人信息。能拿到,不等于可以随手转发。动手写之前先问自己:这份数据该不该存、存多久、谁有权看,这比会不会用 append 更要紧。
二、列表是「序列」家庭的一员
在正式学列表之前,先认识一个更大的概念:序列(sequence)。字符串、列表、元组、range 都属于序列——它们的共同点是:元素排成一队,每个都有自己的位置(下标),可以从 0 开始按位置取。
| 序列成员 | 例子 | 能不能改 |
|---|---|---|
字符串 str | 'abc' | 不能改 |
列表 list | [1, 2, 3] | 能改 |
元组 tuple | (1, 2, 3) | 不能改 |
range | range(5) | 不能改 |
正因为是「一家人」,下面这些操作对它们全都管用(只是结果类型不同):
| 操作 | 写法 | 说明 |
|---|---|---|
| 数个数 | len(s) | 一共几个元素 |
| 按下标取一个 | s[0] / s[-1] | 第 1 个 / 最后一个 |
| 切片取一段 | s[1:4] | 取下标 1、2、3 三个 |
| 判断在不在 | x in s | 返回 True / False |
| 拼接 | s1 + s2 | 接成一个更长的 |
| 重复 | s * 3 | 重复 3 遍 |
| 遍历 | for x in s: | 一个个拿出来 |
s = 'Python' # 字符串也是序列
print(len(s))
print(s[0], s[-1])
print(s[1:4])
print('y' in s)
输出:
6
P n
yth
True
你会看到,字符串上能做的这些事,换成列表也一样能做——因为它们都是序列。这一节学一次,四类东西都能用。
三、创建列表的三种方式
最常用的是第一种,直接写方括号。
方式一:方括号直接写
list1 = [1, 2, 3, 4, 5]
print("list1:", list1)
输出:
list1: [1, 2, 3, 4, 5]
方式二:用 list() 把一串东西变成列表
range() 本身不是列表,套上 list() 就能看见里面的数字:
list2 = list(range(1, 6))
print("list2:", list2)
输出:
list2: [1, 2, 3, 4, 5]
方式三:先建一个空列表,后面再往里加
list3 = []
print("list3:", list3)
输出:
list3: []
列表很自由:类型可以混着放
mixed = [1, "二", 3.0, True]
print(mixed)
输出:
[1, '二', 3.0, True]
还能把列表嵌在列表里,做成一个「表格」的样子:
matrix = [[1, 2], [3, 4]]
print(matrix)
输出:
[[1, 2], [3, 4]]
| 写法 | 什么时候用 | 例子 |
|---|---|---|
[1, 2, 3] | 已知有哪些元素,直接列出来 | nums = [10, 20, 30] |
list(range(...)) | 想要一串连续的数字 | list(range(1, 6)) |
[] | 先空着,待会儿用 append 一个一个加 | todo = [] |
[] 是列表的标志。看到方括号,就想到「一串东西」。空列表 [] 长度为 0,但它是合法的列表,随时能往里加东西。四、索引访问(正索引、负索引、切片、越界)
想从列表里拿出某一个元素,靠索引(位置编号)。编号从 0 开始,不是从 1!
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
print(fruits[0])
print(fruits[1])
print(fruits[-1])
print(fruits[-2])
输出:
苹果
香蕉
葡萄
橙子
记住两句话:正数从 0 往右数;负数从 -1 往左数(-1 是最后一个,-2 是倒数第二个)。
一次拿多个:切片
切片写法 [起点:终点],含起点、不含终点,像「左闭右开」的区间:
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
print(fruits[0:3])
print(fruits[1:-1])
输出:
['苹果', '香蕉', '橙子']
['香蕉', '橙子']
第一个 [0:3] 拿第 0、1、2 个;第二个 [1:-1] 拿中间,去掉头尾。
用循环把每个都拿出来
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
for x in fruits:
print(x, end=" ")
输出:
苹果 香蕉 橙子 葡萄
越界会报错
列表只有 4 个元素(索引 0~3),去拿第 10 个就超出了范围:
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
print(fruits[10])
运行后会报错(逐字照抄解释器):
IndexError: list index out of range
0 开始是最容易栽跟头的地方。想拿「第 3 个」,索引要写 2,不是 3。print(len(列表)) 看一下长度。合法索引是 0 到 长度-1。五、往列表里加东西(append / extend / insert)
列表最棒的一点:它能长大。三个加法各有分工。
append:在末尾加「一个」元素
fruits = ['苹果', '香蕉']
fruits.append('橙子')
print(fruits)
输出:
['苹果', '香蕉', '橙子']
extend:把另一个列表的每个元素都加进来
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list1.extend(list2)
print(list1)
输出:
[1, 2, 3, 4, 5, 6]
insert:插到指定位置
insert(位置, 元素),新元素会占住这个位置,后面的往后挪:
numbers = [1, 2, 4]
numbers.insert(2, 3)
print(numbers)
输出:
[1, 2, 3, 4]
| 方法 | 做了什么 | 例子结果 |
|---|---|---|
append(x) | 在末尾加一个元素 x | [1,2].append(3) → [1,2,3] |
extend([x,y]) | 把 x、y 一个个加进末尾 | [1].extend([2,3]) → [1,2,3] |
insert(i,x) | 插到索引 i 的位置 | [1,2,4].insert(2,3) → [1,2,3,4] |
append 和 extend 容易混。append([4,5,6]) 是把「整个列表」当一个元素塞进去,结果变成 [1,2,3,[4,5,6]];想平铺着加,要用 extend。append 就够了,它最简单也最常用。insert 要搬动后面所有元素,元素很多时会慢一点。课程思政|工匠精神与严谨求实 · 加一个还是加一批
append 和 extend 只差几个字母,效果却差很远:一个把整个列表当成单个元素塞进去,另一个才是一个一个加进来。调程序时最费时间的,往往就是这种「看着差不多」的地方。别凭感觉猜,运行一遍看结果——打印出来对一眼,比在心里推十遍都靠谱。工程上的可靠,就是这么一次次核对攒起来的。
六、从列表里删东西(remove / pop / clear / del)
有加就有删。四种删法,删的对象不一样。
remove:按「内容」删第一个匹配的
animals = ['dog', 'cat', 'bird']
animals.remove('cat')
print(animals)
输出:
['dog', 'bird']
pop:按「位置」删,还会把删掉的元素还给你
colors = ['red', 'green', 'blue']
popped = colors.pop(1)
print("被删掉的是:", popped)
print(colors)
输出:
被删掉的是: green
['red', 'blue']
不带参数写 pop(),会删掉最后一个(栈的用法):
nums = [1, 2, 3]
last = nums.pop()
print(last, nums)
输出:
3 [1, 2]
clear:一键清空,但列表还在
nums = [1, 2, 3]
nums.clear()
print(nums)
输出:
[]
del:直接按位置删,或把整个列表删掉
nums = [10, 20, 30]
del nums[1]
print(nums)
输出:
[10, 30]
del nums 则会把 nums 这个变量整个删掉,之后再访问它会报错。一般不用,清空用 clear() 更稳妥。
| 写法 | 按什么删 | 还能拿回被删的元素吗 |
|---|---|---|
remove(内容) | 值(只删第一个) | 不能 |
pop(位置) | 索引 | 能,返回值就是它 |
clear() | 全部 | 不能,直接变空 |
del 列表[位置] | 索引 | 不能 |
pop,它一边删一边把值交还给你。只想清空,用 clear() 最直白。七、找和数(index / count / in)
要在列表里「找东西」,有三个趁手的工具。
index:某个值在哪儿(第一次出现的位置)
letters = ['a', 'b', 'c', 'b']
print(letters.index('b'))
输出:
1
count:某个值出现了几次
numbers = [1, 2, 2, 3, 2]
print(numbers.count(2))
输出:
3
in:在不在里面(返回 True / False)
list17 = [1, 2, 3]
print(2 in list17)
print(4 in list17)
输出:
True
False
找不到会报错
index 和 remove 要找的值不存在时,会抛 ValueError:
letters = ['a', 'b', 'c']
print(letters.index('z'))
运行后会报错(逐字照抄解释器):
ValueError: 'z' is not in list
in 判断一下再 index,能避免上面的 ValueError。in(安全、返回布尔值);「在的话第几个」用 index(不在会报错);「有几个」用 count。AI 助手小贴士|append 和 extend 是列表的高频混淆点,一句话让 AI 讲透。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:append 和 extend 的区别是什么?[1,2].append([3,4]) 和 [1,2].extend([3,4]) 各得到什么?再出 2 道题考我
八、排序与反转(sort 与 sorted 的区别、sort 返回 None)
把列表排个序,是日常高频操作。这里有个大坑必须先说。
sort:原地排序,不返回新列表
nums = [3, 1, 4, 1, 5, 9, 2, 6]
nums.sort()
print(nums)
输出:
[1, 1, 2, 3, 4, 5, 6, 9]
坑:sort() 返回的是 None
很多人写 sorted_nums = nums.sort(),以为拿到了排好序的列表,其实拿到的是 None:
nums = [3, 1, 2]
result = nums.sort()
print(result)
输出:
None
sort() 是直接把原来的 nums 改掉了(原地排序),它自己不返回任何东西。想要「排好序的新列表又不动原列表」,用 sorted():
nums = [3, 1, 4]
new_nums = sorted(nums)
print(new_nums)
print(nums)
输出:
[1, 3, 4]
[3, 1, 4]
降序与反转
nums = [3, 1, 4, 1, 5, 9, 2, 6]
nums.sort(reverse=True)
print(nums)
输出:
[9, 6, 5, 4, 3, 2, 1, 1]
reverse() 是把顺序整个倒过来,跟大小无关:
nums = [1, 2, 3, 4, 5]
nums.reverse()
print(nums)
输出:
[5, 4, 3, 2, 1]
| 写法 | 动不动原列表 | 返回什么 | 典型用途 |
|---|---|---|---|
nums.sort() | 动(原地改) | None | 就想把原列表排好 |
sorted(nums) | 不动 | 新列表 | 要留着原列表,另存一份排好序的 |
nums.reverse() | 动 | None | 把顺序倒过来 |
sorted() 是内置函数,任何序列都能用,会把排好序的新列表还给你;sort() 是列表自己的方法,直接把原列表改掉,自己什么都不还(返回 None)。课程思政|诚信与职业操守 · 改没改原表,要说清楚
nums.sort() 直接把原列表改了、只返回 None;sorted(nums) 则不动原表,给你一份新的。两种做法都没错,关键是心里清楚自己在动谁,并且让读代码的人一眼看明白。含糊其辞才是真的大坑。命名、注释、返回值,都在替你把话说清楚——这既是严谨,也是对同事的诚实。
九、改元素与列表相加相乘
列表里的元素可以单独改,也可以整体拼接、复制。
改某一个元素
a = [1, 2, 3]
a[1] = 20
print(a)
输出:
[1, 20, 3]
两个列表相加:拼成一个更长的
list12 = [1, 2, 3]
list13 = [4, 5, 6]
list14 = list12 + list13
print(list14)
输出:
[1, 2, 3, 4, 5, 6]
列表乘以数字:重复 N 遍
list15 = [1]
list16 = list15 * 3
print(list16)
输出:
[1, 1, 1]
注意:加和乘都不会改原来的列表,而是产生一个新列表。原列表想变,得自己重新赋值:
a = [1, 2, 3]
a = a + [4, 5]
print(a)
输出:
[1, 2, 3, 4, 5]
+ 和 append 搞混:a = a + [4] 得到新列表;a.append(4) 直接改原列表。也别写 [1,2,3] + 4 —— 列表只能和列表相加,加数字会报错(见报错手册)。zeros = [0] * 5 得到 [0,0,0,0,0]。但里面若是列表要小心(见常见坑第 6 条)。十、常用内置函数与列表推导式
Python 自带几个函数,专门伺候列表这类「一串东西」。
list18 = [1, 2, 3, 4, 5]
print("长度:", len(list18))
print("最大:", max(list18))
print("最小:", min(list18))
print("总和:", sum(list18))
输出:
长度: 5
最大: 5
最小: 1
总和: 15
列表推导式:一行生成列表
这是 Python 很爽的写法:用一行,按规则「变」出一个列表。先看三个例子体会一下:
squares = [i**2 for i in range(1, 11)]
print("1~10 平方:", squares)
输出:
1~10 平方: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
意思是:让 i 从 1 走到 10,把每个 i**2 收进列表。
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even = [i for i in numbers if i % 2 == 0]
print("偶数:", even)
输出:
偶数: [2, 4, 6, 8, 10]
这次多了 if i % 2 == 0:只收偶数。
list22 = [1, 2, 3]
str_list = [str(i) for i in list22]
print("变成文字:", str_list)
输出:
变成文字: ['1', '2', '3']
把每个数字用 str() 转成文字。
再来一个中国味的:从《春晓》里把「春」「晓」两个字挑出来——条件里的 in 也能判断「这个字在不在那串字里」:
poem = '春眠不觉晓处处闻啼鸟'
chars = [c for c in poem if c in '春晓']
print(chars)
输出:
['春', '晓']
推导式的基本长相:[表达式 for 变量 in 一串东西 if 条件]。
for 循环也能做,熟练了再换推导式。十一、多维列表(列表里装列表)
列表的元素可以是任何东西——包括另一个列表。当每个元素本身也是列表时,就成了多维列表(也叫嵌套列表、二维列表)。它最适合表示一张「表格」:一行一个学生,一列一项数据。
students = [
['小明', 92, 88],
['小红', 76, 95],
['小刚', 85, 79],
]
怎么读它?先把它看成「3 个元素」,每个元素本身又是一个列表。要取到具体的数,就从左到右一层层往里钻:
students = [['小明', 92, 88], ['小红', 76, 95], ['小刚', 85, 79]]
print(students[0]) # 第 1 行(整行)
print(students[0][0]) # 第 1 行第 1 列
print(students[1][2]) # 第 2 行第 3 列
输出:
['小明', 92, 88]
小明
95
students[0] 是整行(一个列表),students[0][0] 才是格子里那个值。两个中括号,前一个选行、后一个选列。
students[0][0] 写成 students[0, 0]——普通列表不支持这种写法,会报 TypeError。用双层 for 遍历
students = [['小明', 92, 88], ['小红', 76, 95]]
for row in students: # 外层:一行一行拿
for value in row: # 内层:把这行的每一格拿出来
print(value, end=' ')
print()
输出:
小明 92 88
小红 76 95
常见用法:按行算总分
students = [['小明', 92, 88], ['小红', 76, 95], ['小刚', 85, 79]]
for row in students:
name = row[0]
total = sum(row[1:]) # 从第 2 列开始求和
print(name, '总分', total)
输出:
小明 总分 180
小红 总分 171
小刚 总分 164
矩阵:一个 3×3 的数字方阵
m = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
print(m[1][2]) # 第 2 行第 3 列
print(m[2][0]) # 第 3 行第 1 列
输出:
6
7
坑:[[0] * 3] * 3 造出来的三行其实是「同一行」
bad = [[0] * 3] * 3
bad[0][0] = 9
print(bad) # 三行一起变了!
输出:
[[9, 0, 0], [9, 0, 0], [9, 0, 0]]
原因:[X] * 3 是把同一个 X(同一个列表对象)重复了三遍,三个位置指向的是同一行。正确写法是用推导式,让每行都新建一个:
good = [[0] * 3 for _ in range(3)]
good[0][0] = 9
print(good) # 只有第 1 行变
输出:
[[9, 0, 0], [0, 0, 0], [0, 0, 0]]
m[行][列]。看到 list[i][j] 就读成「第 i 行的第 j 个」。十二、迭代器:for 背后到底发生了什么
你早就习惯了写 for x in 列表:。但 for 到底怎么把元素一个个拿出来的?答案是:列表先「生产」出一个迭代器,for 每次从迭代器里取一个,取完为止。
手动取:iter() 与 next()
nums = [10, 20, 30]
it = iter(nums) # 把列表变成迭代器
print(next(it)) # 取第 1 个
print(next(it)) # 取第 2 个
print(next(it)) # 取第 3 个
输出:
10
20
30
取完了还取,会抛 StopIteration
it = iter([1, 2])
print(next(it))
print(next(it))
print(next(it)) # 没有第 3 个了
运行后最后一行报错是:
StopIteration
for 循环内部其实就在做这件事:不停地 next(),一旦收到 StopIteration 就安静地结束——所以平时你根本看不到这个异常。
迭代器是「一次性」的
nums = [1, 2, 3]
it = iter(nums)
print(list(it)) # 第一次:全取出来了
print(list(it)) # 第二次:空了!
输出:
[1, 2, 3]
[]
可迭代对象 vs 迭代器
| 可迭代对象(Iterable) | 迭代器(Iterator) | |
|---|---|---|
| 特征 | 能被 for 遍历 | 既能被 for 遍历,也能 next() |
| 必备方法 | __iter__ | __iter__ 和 __next__ |
| 能不能反复用 | 能(每次都重新开一个迭代器) | 不能,取完就废 |
| 例子 | 列表、字符串、字典、集合、range | iter([1, 2, 3]) 的结果 |
一句话:列表是「可迭代对象」,但它本身不是「迭代器」。要被 iter() 包装一下,才得到真正的迭代器。
iter() / next(),直接 for 就行。这一节只是为了让你知道 for 的背后是什么——第 24 篇《生成器与迭代器》会顺着这套机制继续往下讲。AI 助手小贴士|列表的基本操作齐了,来三道综合题验收。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:出 3 道列表综合题:去重但保持原来的顺序、把两个等长列表拼成字典、删除列表里所有的偶数。等我写完再对答案
课程思政|科技自立自强 · 循环背后到底怎么走
大家用了无数遍 for x in 列表,却很少想它背后先 iter() 取到迭代器、再不停 next(),取完抛出 StopIteration 才默默收场。数据库、编译器、AI 框架,底层都是这样一层层「取下一个」搭起来的。别只停在会用的层面,多问一句「它内部怎么走」,才可能从使用者变成创造者。
十三、十个基础案例
下面十个例子都很短,建议每个都亲手敲一遍、跑一遍。
1. 这顿外卖平均每样多少钱
prices = [12, 18, 25, 9]
print('平均每样:', sum(prices) / len(prices))
输出:
平均每样: 16.0
2. 最贵和最便宜的那件
prices = [12, 18, 25, 9]
print('最贵', max(prices), '最便宜', min(prices))
输出:
最贵 25 最便宜 9
3. 数一数有几件超过 20 元
prices = [12, 18, 25, 30, 9]
over = 0
for p in prices:
if p > 20:
over += 1
print('超过 20 元的有:', over)
输出:
超过 20 元的有: 2
4. 把价格从高到低排好
prices = [12, 18, 25, 9]
prices.sort(reverse=True)
print(prices)
输出:
[25, 18, 12, 9]
5. 购物车里再加一件
cart = ['奶茶', '炸鸡']
cart.append('薯条')
print(cart)
输出:
['奶茶', '炸鸡', '薯条']
6. 减掉不想要的那件
cart = ['奶茶', '炸鸡', '薯条']
cart.remove('炸鸡')
print(cart)
输出:
['奶茶', '薯条']
7. 从歌单里取出一段
playlist = ['起风了', '晴天', '稻香', '七里香', '告白气球']
print(playlist[1:4])
输出:
['晴天', '稻香', '七里香']
8. 看看好友在不在群里
members = ['阿伟', '小美', '老王']
print('小美' in members)
print('大熊' in members)
输出:
True
False
9. 电影票统统打八折
prices = [50, 45, 60]
sale = [int(p * 0.8) for p in prices]
print(sale)
输出:
[40, 36, 48]
10. 把两个购物车并起来
cart1 = ['奶茶', '炸鸡']
cart2 = ['薯条', '可乐']
print(cart1 + cart2)
输出:
['奶茶', '炸鸡', '薯条', '可乐']
十四、常见坑
坑 1:两个变量指向同一个列表(别名陷阱)
写 b = a 并不是复制,而是让 b 和 a 指向同一个列表。改了 b,a 也跟着变:
a = [1, 2, 3]
b = a
b.append(4)
print('a 也变了:', a)
输出:
a 也变了: [1, 2, 3, 4]
想要一份独立的副本,用 copy():
a = [1, 2, 3]
b = a.copy()
b.append(4)
print('a 没变:', a)
print('b 是副本:', b)
输出:
a 没变: [1, 2, 3]
b 是副本: [1, 2, 3, 4]
坑 2:sort() 返回 None,别赋值给新变量
nums = [3, 1, 2]
new_nums = nums.sort()
print(new_nums)
输出:
None
想要新列表又不动原列表,用 sorted(nums)(见第八节)。
坑 3:remove 只删第一个,而且值不在会报错
nums = [1, 2, 2, 3]
nums.remove(2)
print(nums)
输出:
[1, 2, 3]
列表里有两个 2,remove(2) 只删掉最前面的那个。要全删得用循环或推导式。
坑 4:pop() 不带参数删的是最后一个
nums = [1, 2, 3]
nums.pop()
print(nums)
输出:
[1, 2]
坑 5:索引从 0 开始,数错一位
fruits = ['苹果', '香蕉', '橙子']
print('第 2 个其实是索引 1:', fruits[1])
输出:
第 2 个其实是索引 1: 香蕉
坑 6:乘法复制里的列表是「共享」的
[[]] * 3 造出三个指向同一个空列表的格子,改其中一个,三个一起变:
grid = [[]] * 3
grid[0].append(1)
print(grid)
输出:
[[1], [1], [1]]
copy();需要独立的小列表就用推导式 [[] for _ in range(3)]。is:a is b 为 True 就说明它们共享一个列表,要当心。十五、报错手册
下面这些报错都是本机真实运行出来的,照抄解释器原文。看到眼熟的,直接对照处理。
索引越界 IndexError
lst = [1, 2, 3]
print(lst[5])
运行后会报错(逐字照抄解释器):
IndexError: list index out of range
原因:列表只有 3 个元素(索引 0~2),去拿第 5 个当然没有。先用 len() 看长度。
找不到值 ValueError
lst = [1, 2, 3]
print(lst.index(99))
运行后会报错(逐字照抄解释器):
ValueError: 99 is not in list
原因:index / remove 要找的值不存在。先用 in 判断在不在。
lst = [1, 2, 3]
lst.remove(99)
运行后会报错(逐字照抄解释器):
ValueError: list.remove(x): x not in list
方法名拼错 AttributeError
lst = [1, 2, 3]
lst.appendd(4)
运行后会报错(逐字照抄解释器):
AttributeError: 'list' object has no attribute 'appendd'. Did you mean: 'append'?
原因:append 多打了一个 d。较新的 Python 3 版本会贴心地提示你「你是不是想写 append」。
列表加数字 TypeError
lst = [1, 2, 3]
print(lst + 4)
运行后会报错(逐字照抄解释器):
TypeError: can only concatenate list (not "int") to list
原因:列表只能和列表相加。[1,2,3] + [4] 才行,或者改用 append(4)。
变量没定义 NameError
print(lst[0])
运行后会报错(逐字照抄解释器):
NameError: name 'lst' is not defined. Did you mean: 'list'?
原因:lst 还没创建就用了。创建列表后再访问。
括号没闭合 SyntaxError
lst = [1, 2, 3
运行后会报错(逐字照抄解释器):
SyntaxError: '[' was never closed
原因:少了一个右方括号。代码里的括号(圆、方、花)必须成对出现。
range 里写了字符串 TypeError
print(list(range('5')))
运行后会报错(逐字照抄解释器):
TypeError: 'str' object cannot be interpreted as an integer
原因:range() 只收整数。字符串 '5' 要先 int() 转换。
下标用了全角逗号也会出怪错
lst = [1, 2, 3]
print(lst[1,2])
运行后会报错(逐字照抄解释器):
SyntaxError: invalid character ',' (U+FF0C)
原因:不小心用了中文全角逗号 ,。Python 只认英文半角标点,写代码时切到英文输入法。
TypeError 通常是类型不对(列表加了数字、下标用了字符串);ValueError 是值不合适(找不存在的东西);IndexError 是位置超了。先看最后一行的类型,再往回查。AI 助手小贴士|列表方法十来个,不用背。让 AI 出速查表,再让它出题考你——「被考」是检验学会的最快方式。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:列出 Python 列表最常用的 8 个方法(增删改查排序),每个配一行示例代码,然后出 3 道列表操作小题考我
十六、随堂自测(12 题)
点击选项即可判分,选错的题会立刻展开解析。做完可以看到正确率和错题清单,也可以重新答题。
1列表的索引是从几开始数的?
- A. 从 0 开始
- B. 从 1 开始
- C. 从 -1 开始
- D. 随机,每次都不一样
0 开始,第一个元素是 lst[0],第二个是 lst[1]。这是新手最容易数错的地方,记住「第几个减一」就是索引。2执行 lst = [1, 2, 3, 4] 后,lst[2] 的值是?
- A. 1
- B. 2
- C. 3
- D. 4
2 是「第 3 个」元素,也就是 3。索引从 0 数:0→1,1→2,2→3。3负索引 lst[-1] 表示列表里的哪个元素?
- A. 第 1 个
- B. 最后一个
- C. 倒数第 2 个
- D. 会报错
-1 是最后一个,-2 是倒数第二个。它和 lst[len(lst)-1] 是同一个位置。4下面哪一行能正确创建一个空列表?
- A.
lst = () - B.
lst = {} - C.
lst = "" - D.
lst = []
[]。() 是空元组,{} 是空字典,"" 是空字符串,都不是列表。5从 [1, 2, 3] 里 remove(99) 会发生什么?
- A. 什么都不做
- B. 删除最后一个元素
- C. 报 ValueError
- D. 报 IndexError
remove 按值删,找不到 99 就抛 ValueError: 99 is not in list。删之前先用 in 判断在不在更安全。6nums = [1, 2, 3],执行 nums.pop()(不带参数)会怎样?
- A. 删除第 1 个元素
- B. 删除最后一个元素并把它返回
- C. 把整个列表清空
- D. 报错
pop() 不带参数时删掉最后一个元素,并且把删掉的值交还给你。想删指定位置就写 pop(位置)。7nums = [3, 1, 2] 执行 nums.sort() 后,再 print(nums) 输出?
- A.
[3, 1, 2] - B.
[1, 2, 3] - C. None
- D. 报错
sort() 是原地排序,直接把 nums 改成 [1, 2, 3],打印 nums 看到的就是排好序的结果。8执行 print(nums.sort()) 会打印出什么?
- A.
[1, 2, 3] - B. nums
- C. None
- D. 报错
sort() 只改原列表、自己不返回任何东西,所以它返回 None。想要排好序的新列表要用 sorted(nums)。9下面哪一行代码会报 TypeError?
- A.
lst = [1, 2, 3] - B.
lst.append(4) - C.
lst[0] = 10 - D.
lst + 5
lst + 5 会报 can only concatenate list (not "int") to list。正确是 lst + [5] 或 lst.append(5)。10列表推导式 [i * 2 for i in range(3)] 的结果是?
- A.
[0, 2, 4] - B.
[2, 4, 6] - C.
[0, 1, 2] - D.
[1, 2, 3]
range(3) 给 0,1,2,每个乘 2 得到 0,2,4。推导式就是「对每个 i 算 i*2 收进新列表」。11m = [[1, 2], [3, 4]],那么 m[1][0] 的值是?
- A.
3 - B.
1 - C.
2 - D.
[3, 4]
m[1] 先拿到第 2 行 [3, 4],再 [0] 取这行的第 1 个,也就是 3。两层中括号要从左往右一层层往里钻。12关于迭代器,下面说法正确的是?
- A. 迭代器可以反复使用,取完还能回头再取
- B.
next()取不到元素时会返回 None - C. 列表本身就是迭代器
- D. 迭代器取完后再取会抛
StopIteration
next() 会抛 StopIteration(for 会自动接住它并结束循环)。列表是可迭代对象,要用 iter() 包装一下才得到迭代器。