Python 列表
列表(list)是 Python 最常用的数据结构,没有之一。它像一个可变长、有序、能放任何类型的容器,几乎所有 Python 程序都会用到。这一章把它彻底讲透——增删改查、切片、排序、列表推导式。
1. 什么是列表?
列表是一个有序、可变的序列,用方括号 [] 创建,元素之间用逗号分隔。可变意味着可以增删改,有序意味着元素有固定顺序、可以按下标访问。
# 列表:有序、可变的序列,用方括号 [] 创建
fruits = ["apple", "banana", "cherry"]
numbers = [10, 20, 30, 40, 50]
mixed = [1, "hello", True, 3.14, [1, 2]] # 可以放任意类型,甚至嵌套
# 空列表
empty1 = []
empty2 = list()
# 用 list() 把其他序列转成列表
print(list("hello")) # ['h', 'e', 'l', 'l', 'o']
print(list(range(5))) # [0, 1, 2, 3, 4]
# 查看
print(fruits) # ['apple', 'banana', 'cherry']
print(len(fruits)) # 3 长度列表可以放任意类型的元素,甚至混合类型或嵌套列表——这点和 C/Java 的数组(必须同类型、定长)很不一样,更像是 JavaScript 的 Array。
2. 索引与切片
列表的索引、切片和字符串完全一样——因为它们都是"序列"类型。
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
# 1. 索引访问(和字符串一样)
print(fruits[0]) # apple 第一个
print(fruits[-1]) # elderberry 最后一个
# 2. 切片 [起:止:步长]
print(fruits[1:3]) # ['banana', 'cherry']
print(fruits[:2]) # ['apple', 'banana']
print(fruits[-2:]) # ['date', 'elderberry'] 最后两个
print(fruits[::-1]) # 反转列表
# 3. 修改元素(列表可变!)
fruits[0] = "APPLE"
print(fruits) # ['APPLE', 'banana', ...]
# 4. 判断包含
print("banana" in fruits) # True
print("orange" in fruits) # False区别只是:列表可变,可以通过 list[i] = 新值 修改元素;字符串不行。
3. 添加元素:append / insert / extend
fruits = ["apple", "banana"]
# 1. append:末尾添加一个元素
fruits.append("cherry")
print(fruits) # ['apple', 'banana', 'cherry']
# 2. insert:在指定位置插入
fruits.insert(0, "orange") # 在开头插入
print(fruits) # ['orange', 'apple', 'banana', 'cherry']
# 3. extend:把另一个列表的元素逐个加进来
more = ["grape", "kiwi"]
fruits.extend(more)
print(fruits)
# ['orange', 'apple', 'banana', 'cherry', 'grape', 'kiwi']
# ⚠ append vs extend 的区别(新手常混淆)
a = [1, 2]
a.append([3, 4])
print(a) # [1, 2, [3, 4]] 把整个列表当成一个元素
b = [1, 2]
b.extend([3, 4])
print(b) # [1, 2, 3, 4] 把元素逐个加进来
# + 拼接(返回新列表,不改原列表)
c = [1, 2] + [3, 4]
print(c) # [1, 2, 3, 4]新手最容易混淆 append 和 extend。记住:append 把列表当一个整体加进去,extend 把元素逐个加进去。
4. 删除元素:remove / pop / del / clear
fruits = ["apple", "banana", "cherry", "banana", "date"]
# 1. remove:删除第一个匹配的值
fruits.remove("banana")
print(fruits) # ['apple', 'cherry', 'banana', 'date']
# 如果元素不存在,会报 ValueError
# fruits.remove("orange") # ❌ ValueError
# 2. pop:按索引删除,并返回被删的值
removed = fruits.pop(1) # 删第 1 个,返回它
print(removed) # cherry
print(fruits) # ['apple', 'banana', 'date']
fruits.pop() # 不传索引,删最后一个
print(fruits) # ['apple', 'banana']
# 3. del 语句:按索引删除,不返回值
del fruits[0]
print(fruits) # ['banana']
# 4. clear:清空整个列表
fruits.clear()
print(fruits) # []四种删除方式的区别:
remove(值):按值删第一个匹配项,找不到报错。pop(索引):按索引删,返回被删的值;不传索引删最后一个。del list[索引]:按索引删,不返回值。clear():清空整个列表。
5. 查找与统计
nums = [10, 20, 30, 20, 40, 20]
# 1. index:查找第一个匹配的下标,找不到报错
print(nums.index(30)) # 2
# nums.index(99) # ❌ ValueError
# 2. count:统计元素出现次数
print(nums.count(20)) # 3
# 3. in / not in:判断包含
print(20 in nums) # True
print(99 not in nums) # True
# 4. len / max / min / sum
print(len(nums)) # 6
print(max(nums)) # 40
print(min(nums)) # 10
print(sum(nums)) # 1406. 排序:sort() 与 sorted()
# 1. sort():原地排序(改原列表),返回 None
nums = [3, 1, 4, 1, 5, 9, 2, 6]
nums.sort()
print(nums) # [1, 1, 2, 3, 4, 5, 6, 9]
nums.sort(reverse=True)
print(nums) # [9, 6, 5, 4, 3, 2, 1, 1] 降序
# 2. sorted():返回新列表,不改原列表
nums2 = [3, 1, 4]
result = sorted(nums2)
print(nums2) # [3, 1, 4] 原列表没变
print(result) # [1, 3, 4]
# 3. 字符串排序(按字典序)
words = ["banana", "apple", "cherry"]
words.sort()
print(words) # ['apple', 'banana', 'cherry']
# 4. 用 key 自定义排序规则
students = [("小明", 85), ("小红", 92), ("小刚", 78)]
# 按分数(元组第 2 项)排序
students.sort(key=lambda x: x[1])
print(students)
# [('小刚', 78), ('小明', 85), ('小红', 92)]
# 按分数降序
students.sort(key=lambda x: x[1], reverse=True)
# 5. reverse():原地反转(不是排序!)
x = [1, 3, 2]
x.reverse()
print(x) # [2, 3, 1]sort 和 sorted 的区别非常关键:
list.sort():原地排序,直接改原列表,返回 None。sorted(list):返回新列表,原列表不变。可以用于任何可迭代对象(字符串、字典等)。
用 key 参数自定义排序规则时,lambda 函数(匿名函数,后面讲)极其好用。
7. 列表推导式(重点!Pythonic 之道)
列表推导式是 Python 最具特色的写法之一,一行就能从已有列表生成新列表,比 for 循环简洁、运行也更快。
# 列表推导式:list comprehension
# 经典 Pythonic 写法,一行生成新列表
# 1. 基本语法:[表达式 for 变量 in 序列]
nums = [1, 2, 3, 4, 5]
squares = [n * n for n in nums]
print(squares) # [1, 4, 9, 16, 25]
# 2. 加条件过滤:[表达式 for 变量 in 序列 if 条件]
evens = [n for n in nums if n % 2 == 0]
print(evens) # [2, 4]
# 3. 实用例子
# 把字符串列表全部转大写
names = ["alice", "bob", "charlie"]
upper_names = [name.upper() for name in names]
print(upper_names) # ['ALICE', 'BOB', 'CHARLIE']
# 生成 1~10 的平方,只要偶数的
even_squares = [n*n for n in range(1, 11) if n % 2 == 0]
print(even_squares) # [4, 16, 36, 64, 100]
# 4. 嵌套循环(可读性差,慎用)
pairs = [(i, j) for i in range(2) for j in range(2)]
print(pairs) # [(0,0),(0,1),(1,0),(1,1)]
# 等价的 for 循环写法(对比理解)
squares = []
for n in nums:
squares.append(n * n)语法:[表达式 for 变量 in 序列 if 条件]。读法是"对序列里每个变量,如果满足条件,就生成表达式"。适度使用能提升可读性,但过度嵌套(三层以上)反而难懂,这时还是老老实实写 for 循环。
8. 浅拷贝与深拷贝(重要陷阱)
这是新手最容易踩的大坑:赋值不是复制。
# ⚠ 列表是可变对象,赋值只是"贴标签",不是复制!
a = [1, 2, 3]
b = a # b 和 a 指向同一个列表
b.append(4)
print(a) # [1, 2, 3, 4] <- a 也变了!
# 浅拷贝(复制外层,内层还是共享)
c = a.copy() # 等价写法:a[:] 或 list(a)
c.append(5)
print(a) # [1, 2, 3, 4] <- a 没变
# 但浅拷贝对嵌套列表不够用
nested = [[1, 2], [3, 4]]
shallow = nested.copy()
shallow[0].append(99)
print(nested) # [[1, 2, 99], [3, 4]] <- 内层列表还是共享!
# 深拷贝:用 copy.deepcopy,完全独立
import copy
deep = copy.deepcopy(nested)
deep[0].append(100)
print(nested) # [[1, 2, 99], [3, 4]] <- 这次彻底没变记住:
b = a:只是贴标签,两个变量指向同一对象,改一个另一个也变。- 浅拷贝(
a.copy()/a[:]/list(a)):复制外层,嵌套的内层对象仍共享。 - 深拷贝(
copy.deepcopy(a)):完全独立,递归复制所有层级。
9. 嵌套列表(二维数组)
# 嵌套列表(二维数组)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 访问:matrix[行][列]
print(matrix[0][0]) # 1 第一行第一列
print(matrix[1][2]) # 6 第二行第三列
print(matrix[2]) # [7, 8, 9] 整行
# 遍历二维列表
for row in matrix:
for cell in row:
print(cell, end=" ")
print()
# 输出:
# 1 2 3
# 4 5 6
# 7 8 9处理表格、矩阵、棋盘等二维数据时,嵌套列表是标准做法。
小结
列表是 Python 最常用的数据结构。重点掌握:增删改查(append/insert/extend/remove/pop/del)、切片、sort 与 sorted(原地 vs 返回新)、列表推导式(一行 Pythonic)、浅拷贝 vs 深拷贝(赋值不是复制!)。下一篇看列表的"亲兄弟"——元组。
← 上一篇 Python 字符串
下一篇 Python 元组 →