列表(List)是Python内置的四大数据结构之一,它是一个有序、可变的容器,可以存放任意类型的元素。无论是处理数据、构建中间结果,还是实现算法逻辑,列表几乎无处不在。掌握列表的各种操作方法,是写出简洁高效Python代码的基础。本文将从创建列表开始,依次讲解增删改查、切片、遍历以及列表推导式等核心操作,并分析一些容易踩坑的细节。

一、列表的创建与查询操作
创建列表最直接的方式是使用方括号,元素之间用逗号分隔。列表中的元素可以是任意类型,甚至可以嵌套另一个列表。除了方括号语法,还可以使用list()构造函数把其他可迭代对象转换为列表。
# 创建列表的几种方式
nums = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True, [10, 20]]
from_range = list(range(0, 10, 2)) # [0, 2, 4, 6, 8]
from_string = list("abc") # ['a', 'b', 'c']
print(from_range, from_string)查询操作主要依赖索引和index()方法。Python的索引从0开始,负索引则从末尾往前数,例如nums[-1]表示最后一个元素。需要注意的是,访问不存在的索引会抛出IndexError异常,因此在不确定长度时应先做判断。
nums = [10, 20, 30, 40]
print(nums[0]) # 10
print(nums[-1]) # 40
pos = nums.index(30)
print("元素30的下标是:", pos)
# 统计相关
print(len(nums)) # 长度 4
print(nums.count(20)) # 元素20出现1次
print(20 in nums) # True,成员判断二、添加与删除元素的多种方式
添加元素有三个常用方法:append()在末尾追加单个元素,extend()把另一个可迭代对象的元素逐个追加进来,insert()在指定位置插入元素。最容易犯的错误是把append()当成批量添加来用——append([4, 5])会把整个列表作为一个元素塞进去,形成嵌套结构,而不是合并两个列表。
nums = [1, 2, 3] nums.append(4) # [1, 2, 3, 4] nums.append([5, 6]) # [1, 2, 3, 4, [5, 6]],注意嵌套! nums.extend([7, 8]) # [1, 2, 3, 4, [5, 6], 7, 8] nums.insert(0, 0) # 在下标0处插入0 print(nums) # 也可以用 + 和 * 拼接 print([1, 2] + [3]) # [1, 2, 3] print([0] * 3) # [0, 0, 0]
删除元素同样有多重手段,各有适用场景。remove()按值删除第一个匹配项,找不到会抛ValueError;pop()按下标删除并返回该元素,不传下标时默认删除最后一个;del语句既可以删单个元素也可以删整段切片;clear()则清空整个列表。
nums = [10, 20, 30, 40, 50] nums.remove(30) # 按值删除 last = nums.pop() # 删除并返回50 second = nums.pop(0) # 删除并返回10 del nums[0] # 删除剩余的第一个元素 print(nums) # [40] nums.clear() print(nums) # []
三、修改、排序与切片技巧
由于列表是可变对象,可以直接通过索引赋值来修改元素,也可以对一段切片整体赋值,切片赋值甚至允许新旧长度不一致,这是列表非常灵活的特性。
nums = [1, 2, 3, 4, 5] nums[0] = 100 # 单个修改 nums[1:3] = [20, 30, 35] # 切片替换,长度可不同 print(nums) nums.sort() # 原地升序排序 print(nums) nums.sort(reverse=True) # 降序排序 print(nums) print(sorted(nums)) # 返回新列表,不改原列表 nums.reverse() # 原地反转 print(nums)
切片语法列表[起:止:步长]是列表操作的精华所在。左闭右开区间,三个参数都可省略。负步长可以实现倒序取值,这在反转字符串、取偶数位元素等场景中非常实用。
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(nums[2:6]) # [2, 3, 4, 5] print(nums[:3]) # [0, 1, 2] print(nums[::2]) # [0, 2, 4, 6, 8] 偶数下标 print(nums[::-1]) # 整个列表反转 copy_nums = nums[:] # 切片复制生成新列表 print(copy_nums is nums) # False
这里要特别区分浅拷贝与引用。直接赋值b = a只是让两个变量指向同一个列表,修改其中一个另一个也会变;而a[:]或a.copy()会创建新的外层列表,但内部嵌套对象仍然是共享的引用,这就是浅拷贝。如果列表中嵌套了可变对象且需要完全独立,应使用copy.deepcopy()。
四、遍历与列表推导式
遍历列表除了最基础的for循环,还经常需要同时拿到下标和值,这时enumerate()比手动维护计数器优雅得多。需要并行遍历多个列表时,zip()是最佳选择。
names = ["Alice", "Bob", "Cindy"]
scores = [90, 85, 77]
for i, name in enumerate(names):
print(i, name)
for name, score in zip(names, scores):
print(f"{name}: {score}")列表推导式是Python最具代表性的语法糖,它可以用一行代码完成映射、过滤的组合操作,执行效率也比等价的for循环加append更高。其基本结构是[表达式 for 变量 in 可迭代对象 if 条件]。
# 生成1到10的平方 squares = [x ** 2 for x in range(1, 11)] print(squares) # 过滤出偶数 evens = [x for x in range(20) if x % 2 == 0] print(evens) # 带条件表达式的映射 labels = ["偶" if x % 2 == 0 else "奇" for x in range(5)] print(labels) # 嵌套推导:展平二维列表 matrix = [[1, 2], [3, 4], [5, 6]] flat = [item for row in matrix for item in row] print(flat) # [1, 2, 3, 4, 5, 6]
需要注意的是,推导式虽然简洁,但不宜过度嵌套。两层以上的嵌套推导可读性会明显下降,此时改写为普通循环或者提取函数更利于维护。另外在数据量大且只需遍历一次的场景下,生成器表达式比列表推导式更省内存,把方括号换成圆括号即可。
总结
列表操作的核心在于理解它是可变序列这一本质:按索引增删改查、灵活的切片语法、原地排序与反转,以及推导式带来的简洁表达。实际编码中要特别留意引用与浅拷贝的区别、切片的左闭右开规则,以及append与extend的差异。把这些细节吃透,列表就会成为你手中最趁手的数据处理工具。