基础

Python 列表(list):方法、切片、排序、append、元组与集合

更新于: · Skillaria.Top

列表(list)是 Python 中有序、可变的集合,用方括号书写,例如 [250, 1200, 99]:可以用 append 添加元素,也可以插入、删除、切片和排序。sort 原地排序并返回 None,而 sorted 返回一个新的已排序列表。

Python 中的列表(list)是一组有序的任意值,写在方括号中,并且可以修改:可以在末尾添加元素,在中间插入,删除,排序。它是语言中最常用的集合:文件的行、一个月的支出、API 的响应,几乎都从列表开始。下面完整讲解 python list:创建、方法、切片、排序、列表推导式、复制,最后是元组和集合。

什么是 Python 列表

列表按你设定的顺序保存元素,并通过从 0 开始的索引访问。同一个列表中可以放不同类型的值,不过实际中通常保存同类数据。

amounts = [250, 1200, 99]
print(amounts[0])     # 250 — 第一个元素
print(amounts[-1])    # 99 — 最后一个元素
amounts[1] = 1300     # 列表是可变的
print(len(amounts))   # 3 — 列表长度

列表的长度由函数 len() 返回。访问不存在的索引会得到 IndexError: list index out of range。

创建列表

empty = []                       # 空列表
also_empty = list()              # 用 list 函数创建,效果相同
nums = [1, 2, 3]
chars = list("abc")              # ['a', 'b', 'c']
digits = list(range(5))          # [0, 1, 2, 3, 4]
zeros = [0] * 4                  # [0, 0, 0, 0]

函数 list() 可以把任何可迭代对象转换为列表:字符串、range、集合、字典的键。

append 与其他列表方法

append 在列表末尾添加一个元素,是 Python 中最常用的方法之一。它原地修改列表,并返回 None。

amounts = [250, 1200]
amounts.append(450)          # [250, 1200, 450]
amounts.extend([10, 20])     # [250, 1200, 450, 10, 20]
amounts.insert(0, 5)         # [5, 250, 1200, 450, 10, 20]
amounts.remove(1200)         # 删除第一个值为 1200 的元素
last = amounts.pop()         # 20 — 删除并返回最后一个元素

常见错误:a.append([10, 20]) 只会添加一个元素,即嵌套的列表,而不是两个数字。要添加多个元素,应使用 extend。

方法作用
append(x)在末尾添加 x
extend(iter)添加序列中的所有元素
insert(i, x)在索引 i 之前插入 x
remove(x)删除第一次出现的 x(不存在则 ValueError)
pop(i=-1)删除并返回索引 i 处的元素
index(x)第一次出现的索引
count(x)x 出现的次数
sort()原地排序
reverse()原地反转
copy()浅复制
clear()清空列表

按索引或整个范围删除元素也可以使用 del 语句:del a[0]、del a[1:3]。对列表很有用的内置函数有:len、sum、min、max、sorted、reversed、enumerate、zip。

Python 中的切片

切片按 a[start:stop:step] 的格式取出列表的一部分:从 start(包含)到 stop(不包含),步长为 step。每一部分都可以省略。切片总是返回一个新列表。

a = [0, 1, 2, 3, 4, 5]
print(a[1:4])     # [1, 2, 3]
print(a[:2])      # [0, 1] — 前两个
print(a[-2:])     # [4, 5] — 最后两个
print(a[::2])     # [0, 2, 4] — 每隔一个
print(a[::-1])    # [5, 4, 3, 2, 1, 0] — 反转
print(a[:])       # 整个列表的副本

与索引不同,切片超出列表范围不会报错:a[10:20] 只会返回 []。还可以给切片赋值来替换列表的一部分:a[1:3] = ["x", "y", "z"]。

字符串切片

切片对所有序列都适用,包括字符串和元组:

s = "Python 3.15"
print(s[:6])      # Python
print(s[-4:])     # 3.15
print(s[::-1])    # 51.3 nohtyP

字符串不能通过切片修改——字符串是不可变的,切片会创建一个新字符串。

列表排序:sort 与 sorted

这是新手最容易混淆的地方。sort 方法在列表内部重新排列元素,并返回 None。函数 sorted 不改动原列表,而是返回一个新的已排序列表。

amounts = [250, 1200, 99]
amounts.append(450)
print(sorted(amounts))     # [99, 250, 450, 1200] — 新副本
print(amounts)             # [250, 1200, 99, 450] — 原列表不变

result = amounts.sort()    # 原地排序
print(result, amounts)     # None [99, 250, 450, 1200]

这就是经典的“为什么我得到 None”问题:a = a.sort() 会把列表覆盖成 None。应该写 a.sort(),或者 a = sorted(a)。

关键字 key 与逆序

两者都接受 key 和 reverse 参数。key 是一个函数,元素将根据它的结果进行比较。

words = ["coffee", "Taxi", "subscription"]
print(sorted(words, key=len))               # ['Taxi', 'coffee', 'subscription']
print(sorted(words, key=str.lower))         # 不区分大小写
print(sorted([3, 1, 2], reverse=True))      # [3, 2, 1]

expenses = [("餐饮", 650), ("电影", 120), ("打车", 300)]
expenses.sort(key=lambda e: e[1])           # 按金额排序

Python 的排序是稳定的:键相同的元素保持原来的相对顺序。另一个区别在于适用范围:sorted 可以用于任何序列(字符串、字典、集合),而 sort 只有列表才有。

反转列表

有三种方式,行为各不相同:

  • a.reverse() — 原地反转,返回 None;
  • a[::-1] — 生成一个新的反转列表;
  • reversed(a) — 惰性迭代器,适合在循环中使用:for x in reversed(a):。

遍历列表

items = ["咖啡", "地铁", "电影"]
for item in items:
    print(item)

for i, item in enumerate(items, start=1):
    print(i, item)          # 1 咖啡,2 地铁,3 电影

print("电影" in items)      # True — 检查是否包含

不要在遍历列表的同时删除其中的元素,否则会漏掉一些元素。应该用列表推导式生成一个新列表,或者遍历副本 a[:]。

列表推导式(list comprehension)

列表推导式可以用一行代码构造新列表:表达式、循环以及可选的条件。

squares = [n * n for n in range(6)]          # [0, 1, 4, 9, 16, 25]
big = [a for a in [250, 1200, 99] if a > 200]  # [250, 1200]
names = [s.strip().title() for s in [" alice ", "bob"]]   # ['Alice', 'Bob']

列表推导式通常比带 append 的循环更快,也更易读。但如果逻辑无法放进一行清晰的代码中,普通的循环更好。

列表的合并、相加与相减

a = [1, 2, 3]
b = [3, 4]
print(a + b)       # [1, 2, 3, 3, 4] — 新列表
a += b             # 相当于 a.extend(b)
print([*a, *b])    # 解包到新列表中

Python 中没有用 - 来做列表相减的运算符。要从一个列表中去掉另一个列表的元素,可以使用推导式:[x for x in a if x not in set(b)]。列表的交集最方便的方法是借助集合:set(a) & set(b)(这会丢失顺序和重复元素)。

嵌套列表与二维列表

列表的列表是保存表格或矩阵的简单方式:

matrix = [[1, 2, 3], [4, 5, 6]]
print(matrix[1][2])     # 6
grid = [[0] * 3 for _ in range(2)]   # 正确
bad = [[0] * 3] * 2                  # 陷阱:两个引用指向同一个列表
bad[0][0] = 9
print(bad)              # [[9, 0, 0], [9, 0, 0]]

列表解包

first, second, third = [10, 20, 30]
head, *rest = [1, 2, 3, 4]      # head=1, rest=[2, 3, 4]
print(*["a", "b"], sep=", ")    # a, b — 不带括号打印列表元素

如果变量数量与列表长度不一致,会得到 ValueError——这时星号变量就能派上用场。

复制列表

b = a 并不会复制列表,而是给同一个对象再贴上一个标签:通过 b 做的修改在 a 中也能看到。独立的副本需要显式创建:a.copy()、list(a) 或 a[:]。对于嵌套数据,这还不够——内层列表依然共享,需要使用 copy.deepcopy(a)。

import copy
a = [[1, 2], [3]]
b = a.copy()
b[0].append(99)
print(a)                 # [[1, 2, 99], [3]] — 嵌套列表是共享的
c = copy.deepcopy(a)     # 完全独立的副本

元组:不可变的列表

元组(tuple)与列表相似,但创建后不能修改。这向读者传达了一个明确的信号:这是一条由固定字段组成的记录,而不是可以增长的集合。元组很容易解包,函数通常正是用元组返回多个值。

expense = (250, "咖啡")
amount, item = expense
expense[0] = 300
# TypeError: 'tuple' object does not support item assignment

由不可变值组成的元组是可哈希的,因此可以用作字典的键。只有一个元素的元组要写逗号:(5,)。

集合:只保存唯一值

集合(set)只保存唯一的值,并且不记录顺序。它是去重以及检查“是否存在”的最快方法,还支持交集、并集和差集。

jan = {"餐饮", "打车", "电影"}
feb = {"餐饮", "订阅"}
print(jan & feb)    # {'餐饮'}
print(feb - jan)    # {'订阅'}
unique = list(dict.fromkeys([3, 1, 3, 2]))   # [3, 1, 2] — 去重且保持顺序
empty = set()       # {} 是空字典!

如何选择集合类型

任务集合类型
需要顺序并且可以修改list
固定的记录tuple
按键查找dict
唯一性,检查是否存在set
不可变的设置frozendict(Python 3.15)

x in list 会逐个比较元素,而 x in set 几乎是瞬间完成的。如果在循环中多次检查一个大列表中是否包含某值,把它转换为集合。

小结

Python 列表是有序、可变的集合:append 和 extend 用于添加,pop 和 remove 用于删除,切片 a[start:stop:step] 用于截取部分,sort 原地排序并返回 None,而 sorted 返回新列表。复制要显式进行;固定的记录使用元组,唯一的值使用集合。列表、元组、字典和集合在课程《Python 3.15:从新手到专家》中都有实践讲解。

常见问题

Python 列表和数组有什么区别?

Python 中没有其他语言意义上的内置数组,它的角色由列表承担,列表可以同时保存不同类型的值。紧凑的数值数组可以使用 array 模块或 NumPy 库。

如何查找列表中某个元素的索引?

方法 a.index(x) 返回第一次出现的索引,如果元素不存在则抛出 ValueError。因此调用前最好先检查 x in a。

如何在保持顺序的情况下去除列表中的重复项?

使用 list(dict.fromkeys(a)):字典的键是唯一的,并且保持插入顺序。list(set(a)) 也能去重,但不保留顺序。

如何把字符串列表合并为一个字符串?

使用字符串的 join 方法:", ".join(["a", "b", "c"]) 得到 "a, b, c"。所有元素必须是字符串,数字要先用 map(str, a) 转换。

列表中可以放不同类型的元素吗?

可以,一个列表可以同时包含数字、字符串、其他列表以及任何对象。但对这样的列表排序通常需要提供 key 参数,否则比较数字和字符串会引发 TypeError。

通过视频学习本主题

课程“Python 3.15: от новичка до профи”结合实践详细讲解了这一主题。

前往课程