在 Python 3 中,列表(List) 是最常用、最灵活的数据结构。它相当于其他语言中的“动态数组”,但功能更强大。
列表的核心特征是:有序、可变(Mutable)、允许重复元素、可以存储不同类型的数据。
下面我将从基础操作、核心切片技巧、高效推导式到常见陷阱,为你全面解析 Python 3 列表。
一、 创建与初始化
# 1. 空列表
empty_list = []
empty_list_2 = list()
# 2. 包含元素的列表
fruits = ["apple", "banana", "cherry"]
# 3. 混合类型 (Python 允许,但不推荐用于复杂逻辑)
mixed = [1, "hello", 3.14, True]
# 4. 快速生成列表
zeros = [0] * 5 # [0, 0, 0, 0, 0]
range_list = list(range(5)) # [0, 1, 2, 3, 4]二、 增删改查 (CRUD)
1. 查 (Access)
支持正向索引和反向索引。
nums = [10, 20, 30, 40, 50]
print(nums[0]) # 10 (第一个)
print(nums[-1]) # 50 (最后一个)
# print(nums[10]) # ❌ IndexError: list index out of range2. 改 (Update)
直接通过索引赋值。
nums[1] = 99
print(nums) # [10, 99, 30, 40, 50]3. 增 (Add)
append(): 尾部添加单个元素 (O(1),最快)。insert(): 指定位置插入 (O(n),较慢,因为要移动后续元素)。extend(): 批量追加另一个可迭代对象。
nums.append(60) # [10, 99, 30, 40, 50, 60]
nums.insert(0, 5) # [5, 10, 99, 30, 40, 50, 60]
nums.extend([70, 80]) # [5, 10, ..., 60, 70, 80]4. 删 (Remove)
pop(): 弹出并返回指定索引的元素(默认最后一个)。remove(): 删除第一个匹配值的元素。del: 根据索引或切片删除。clear(): 清空列表。
last = nums.pop() # 删除并返回 80
nums.remove(99) # 删除值为 99 的元素
del nums[0] # 删除第一个元素三、 灵魂技巧:切片 (Slicing) 🌟
切片是 Python 列表最强大的功能之一,语法为 list[start:stop:step]。
- 左闭右开:包含
start,不包含stop。 - 步长:默认为 1。
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nums[2:5]) # [2, 3, 4] (索引 2 到 4)
print(nums[:3]) # [0, 1, 2] (从头开始)
print(nums[7:]) # [7, 8, 9] (直到结尾)
print(nums[::2]) # [0, 2, 4, 6, 8] (每隔一个取一个)
print(nums[::-1]) # [9, 8, ..., 0] (🔥 经典用法:列表反转)💡 注意:切片操作返回的是原列表的一个浅拷贝(Shallow Copy),修改切片结果不会影响原列表。
四、 现代 Python 利器:列表推导式 (List Comprehension)
这是区分新手和高手的关键。当需要根据旧列表生成新列表时,永远优先使用推导式,它比传统的 for 循环 + append 更快、更简洁。
语法:[表达式 for 变量 in 可迭代对象 if 条件]
# 场景 1:生成 0-9 的平方
squares = [x**2 for x in range(10)]
# 等价于:
# squares = []
# for x in range(10):
# squares.append(x**2)
# 场景 2:过滤偶数并转换为字符串
evens_str = [str(x) for x in range(10) if x % 2 == 0]
# 输出: ['0', '2', '4', '6', '8']
# 场景 3:嵌套循环 (生成坐标点)
points = [(x, y) for x in range(2) for y in range(2)]
# 输出: [(0, 0), (0, 1), (1, 0), (1, 1)]五、 常用内置函数与方法
| 方法/函数 | 作用 | 时间复杂度 |
|---|---|---|
len(list) | 获取长度 | O(1) |
list.sort() | 原地排序 (修改原列表) | O(n log n) |
sorted(list) | 返回新的排序列表 (不修改原列表) | O(n log n) |
list.reverse() | 原地反转 | O(n) |
list.index(val) | 查找值第一次出现的索引 | O(n) |
list.count(val) | 统计值出现的次数 | O(n) |
val in list | 判断值是否存在 | O(n) (慢!见下文陷阱) |
六、 ⚠️ 三大常见陷阱 (避坑指南)
陷阱 1:浅拷贝与引用问题
当你使用 = 赋值列表时,只是复制了引用(指针),而不是复制数据。修改其中一个,另一个也会变。
a = [1, 2, 3]
b = a # b 指向同一个内存地址
b.append(4)
print(a) # [1, 2, 3, 4] 😱 a 也被改变了!
# ✅ 正确拷贝方式:
c = a[:] # 切片拷贝
d = a.copy() # 方法拷贝
e = list(a) # 构造函数拷贝(注:如果列表中包含嵌套列表,以上方法均为浅拷贝,需使用 copy.deepcopy())
陷阱 2:在遍历列表时删除元素
这会导致索引错乱,跳过某些元素。
nums = [1, 2, 2, 3, 4]
# ❌ 错误做法
for n in nums:
if n == 2:
nums.remove(n)
# 结果可能不符合预期,因为列表长度在变化
# ✅ 正确做法 1:列表推导式 (推荐)
nums = [n for n in nums if n != 2]
# ✅ 正确做法 2:倒序遍历
for i in range(len(nums)-1, -1, -1):
if nums[i] == 2:
del nums[i]陷阱 3:误用 in 进行大量查找
if x in my_list 的时间复杂度是 O(n)。如果列表很大且需要频繁查找,请将其转换为 集合 (set),查找速度将提升至 O(1)。
# 慢
if target in huge_list: ...
# 快
huge_set = set(huge_list)
if target in huge_set: ...七、 总结:列表 vs 其他结构
- 需要有序且频繁修改? 👉 List
- 需要快速查找是否存在? 👉 Set
- 需要键值对映射? 👉 Dict
- 数据不可变且作为字典 Key? 👉 Tuple
列表是 Python 的基石。掌握切片和推导式,你就掌握了 Python 列表的精髓。
你想看一个具体的实战例子吗?比如:如何用一行代码实现矩阵转置,或者如何高效合并两个有序列表?随时告诉我!