Skip to content

列表

为什么需要列表

前面学变量的时候,一个名字只装一个值:

a = 1
b = 2
c = 3

存一个数、一个名字,这样够用。可是如果要存全班 50 个同学的姓名呢?难道要起 50 个名字、写 50 行赋值?显然太笨了。

我们需要一种能一次装下很多值的东西,这就是列表(list)。

names = ["tom", "jerry", "spike"]
print(names)
['tom', 'jerry', 'spike']

列表用方括号 [] 表示,里面的值用逗号隔开。它像一排有编号的盒子:盒子按顺序排好,每个盒子放一个值。

列表里可以放数字、字符串,也可以混着放,甚至可以再放一个列表。

l = [1, "hello", 3.14, True]
print(l)
[1, 'hello', 3.14, True]

下标:从 0 开始

每个盒子都有编号,叫做下标。编号从 0 开始,不是从 1 开始,这是编程里常见的习惯。

第一个元素是 l[0],第二个是 l[1],第 n 个是 l[n-1]。

l1 = [1, 2, 3, 4]

print(l1[0])
print(l1[1])
print(l1[3])
1
2
4

l1[3] 取出的是第 4 个元素。数下标时要记住「从 0 数」。

用 -1 取最后一个

如果列表很长,我们往往不知道最后一个的下标是多少。用负数下标可以从末尾往回数:-1 是最后一个,-2 是倒数第二个。

l = ["a", "b", "c"]

print(l[-1])
print(l[-2])
c
b

这样不管列表多长,l[-1] 总是最后一个。

修改元素

列表和字符串有一个重要区别:字符串里的字符改不了,列表可以按下标直接改。

l = [1, 2, 3]
print(l)

l[0] = 100
print(l)
[1, 2, 3]
[100, 2, 3]

这一句 l[0] = 100 把第一个盒子里的值换成了 100。列表因此也叫「可变」的。

切片:取一段

要一次取出连续的几个元素,用切片:l[起点:终点]。规则是包含起点,不包含终点。

l = [1, 2, 3, 4, 5]

print(l[1:3])
print(l[:2])
print(l[2:])
[2, 3]
[1, 2]
[3, 4, 5]
  • l[1:3] 从下标 1 取到下标 2,不包含 3
  • l[:2] 省略起点,从最前面开始
  • l[2:] 省略终点,一直取到最后

切片得到的是新列表,改动它不会影响原来的列表。这一点后面会再提到。详见 切片。

长度和遍历

len(l) 得到列表里元素的个数。

l = ["tom", "jerry", "spike"]
print(len(l))
3

要逐个处理每个元素,用 for 遍历,不用自己管下标:

for name in l:
    print(name)
tom
jerry
spike

如果同时需要下标和值,用 enumerate。它是内置函数,括号里能放哪些类型,见 for 循环。

for i, name in enumerate(l):
    print(i, name)
0 tom
1 jerry
2 spike

判断元素是否存在

用 in 判断某个值在不在列表里,结果是 True 或 False。

l = ["tom", "jerry"]

print("tom" in l)
print("spike" in l)
True
False

列表可以嵌套

列表里还能放列表,像表格一样按行、列两层下标访问。

grid = [[1, 2], [3, 4]]

print(grid[0])
print(grid[1][0])
[1, 2]
3

grid[1][0] 先取第 2 行,再取这一行的第 1 个元素。

排序

sort 直接改原列表,sorted 返回一个新列表、原列表不动。加 reverse=True 可以从大到小。

nums = [3, 1, 2]

print(sorted(nums))
print(nums)

nums.sort()
print(nums)

print(sorted(nums, reverse=True))
[1, 2, 3]
[3, 1, 2]
[1, 2, 3]
[3, 2, 1]

注意第 4 行打印 nums 还是 [3, 1, 2],说明 sorted 没有动原列表。

列表推导式

如果要把一个列表里的每个元素都算一遍,得到一个新列表,可以用列表推导式,写起来更短。

nums = [0, 1, 2, 3, 4]

squares = [n * n for n in nums]
print(squares)

odds = [n for n in nums if n % 2 == 1]
print(odds)
[0, 1, 4, 9, 16]
[1, 3]
  • [n * n for n in nums] 把每个元素平方
  • [n for n in nums if n % 2 == 1] 只留下奇数

一开始看不懂不要紧,先用 for 循环写,等熟悉了再用这种写法。

合并和重复

两个列表可以用 + 拼起来,用 * 重复若干次。

a = [1, 2]
b = [3, 4]

print(a + b)
print(a * 2)
print([0] * 3)
[1, 2, 3, 4]
[1, 2, 1, 2]
[0, 0, 0]

[0] * 3 常用来一次造出一个全是 0 的列表。

常见坑

切片是新列表,改它不影响原列表。

l = [1, 2, 3]
part = l[:2]
part[0] = 100

print(part)
print(l)
[100, 2]
[1, 2, 3]

但 b = a 不复制,只是又起了个名字。

a = [1, 2, 3]
b = a
b.append(4)

print(a)
[1, 2, 3, 4]

两个名字指向同一个列表,改一个另一个也跟着变。真要独立一份,用 b = a[:] 或 b = list(a)。

下标越界会报 IndexError。

l = [1, 2, 3]
print(l[3])
IndexError: list index out of range

列表只有下标 0、1、2,没有 3,所以报错。

小结

  • 列表用来存一组有顺序的值,用 [] 表示
  • 下标从 0 开始,负数从末尾数
  • 列表可修改,字符串不可修改
  • l[起点:终点] 做切片,切片是新列表
  • len 看长度,for 遍历,in 判断存在
  • sort 改原列表,sorted 返回新列表
  • b = a 不复制,b = a[:] 才复制
  • 常用的追加、删除、插入见 列表函数

用 python examples/list.py 运行本节的例子。