Python list常规用法与经典技巧

6 阅读8分钟

Python list常规用法与经典技巧


一、基础用法

1. 创建列表

lst = [1, 2, 3]              # 字面量
lst = []                     # 空列表
lst = list()                 # 空列表
lst = list("abc")            # ['a', 'b', 'c']
lst = list(range(5))         # [0, 1, 2, 3, 4]
lst = [0] * 5                # [0, 0, 0, 0, 0]
lst = [i for i in range(5)]  # [0, 1, 2, 3, 4]

2. 访问元素

lst = [10, 20, 30, 40, 50]

lst[0]      # 10,第一个
lst[-1]     # 50,最后一个
lst[1:3]    # [20, 30],切片
lst[:2]     # [10, 20],前两个
lst[2:]     # [30, 40, 50],从第三个到末尾
lst[::2]    # [10, 30, 50],步长 2
lst[::-1]   # [50, 40, 30, 20, 10],反转

3. 增

lst = [1, 2, 3]

lst.append(4)          # 尾部添加,[1,2,3,4]
lst.insert(0, 0)       # 指定位置插入,[0,1,2,3,4]
lst.extend([5, 6])     # 批量添加,[0,1,2,3,4,5,6]
lst += [7]             # 等价于 extend,[0,1,2,3,4,5,6,7]

append vs extend

lst = [1, 2]
lst.append([3, 4])     # [1, 2, [3, 4]],把列表当整体
lst = [1, 2]
lst.extend([3, 4])     # [1, 2, 3, 4],拆开逐个加

4. 删

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

lst.pop()              # 删尾部,返回 5,lst = [1,2,3,4]
lst.pop(0)             # 删指定位置,返回 1,lst = [2,3,4]
lst.remove(3)          # 按值删第一个匹配项,lst = [2,4]
del lst[0]             # 按索引删,lst = [4]
lst.clear()            # 清空,lst = []

remove vs pop

  • remove(value):按值删,不知道索引时用。
  • pop(index):按索引删,返回被删的值。

5. 改

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

lst[0] = 100           # [100, 2, 3, 4, 5]
lst[1:3] = [20, 30]    # 切片赋值,[100, 20, 30, 4, 5]
lst[1:3] = [1, 2, 3]   # 长度可以变,[100, 1, 2, 3, 4, 5]

6. 查

lst = [10, 20, 30, 20]

lst[0]                 # 按索引,10
lst.index(20)          # 按值找索引,1(第一个匹配)
lst.count(20)          # 统计出现次数,2
20 in lst              # 成员判断,True
len(lst)               # 长度,4

7. 排序与反转

lst = [3, 1, 4, 1, 5]

lst.sort()                    # 原地排序,[1, 1, 3, 4, 5]
lst.sort(reverse=True)        # 降序,[5, 4, 3, 1, 1]
lst.sort(key=len)             # 按自定义规则
lst.reverse()                 # 原地反转

sorted(lst)                   # 返回新列表,不改原列表
sorted(lst, reverse=True)     # 降序
sorted(lst, key=lambda x: -x) # 按自定义规则

sort vs sorted

  • lst.sort():原地排序,返回 None,改原列表。
  • sorted(lst):返回新列表,原列表不变。

二、经典用法

1. 列表推导式

# 平方
squares = [x**2 for x in range(5)]        # [0, 1, 4, 9, 16]

# 筛选偶数
evens = [x for x in range(10) if x % 2 == 0]   # [0, 2, 4, 6, 8]

# 转换 + 筛选
strs = ["1", "-2", "3"]
positives = [int(s) for s in strs if int(s) > 0]   # [1, 3]

# 嵌套
pairs = [(x, y) for x in [1, 2] for y in ["a", "b"]]
# [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]

2. 遍历时带索引:enumerate

fruits = ["apple", "banana", "cherry"]

for i, fruit in enumerate(fruits):
    print(i, fruit)
# 0 apple
# 1 banana
# 2 cherry

# 从 1 开始
for i, fruit in enumerate(fruits, start=1):
    print(i, fruit)

3. 同时遍历多个列表:zip

names = ["小明", "小红", "小刚"]
ages = [25, 30, 28]

for name, age in zip(names, ages):
    print(name, age)

# 转成列表
pairs = list(zip(names, ages))
# [('小明', 25), ('小红', 30), ('小刚', 28)]

# 解压
names, ages = zip(*pairs)

4. 扁平化嵌套列表

nested = [[1, 2], [3, 4], [5, 6]]

# 方法一:列表推导式
flat = [x for sublist in nested for x in sublist]
# [1, 2, 3, 4, 5, 6]

# 方法二:itertools.chain
import itertools
flat = list(itertools.chain(*nested))

5. 去重且保持顺序

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

# 方法一:dict.fromkeys(推荐)
unique = list(dict.fromkeys(lst))
# [3, 1, 2, 4]

# 方法二:set(不保持顺序)
unique = list(set(lst))
# 顺序可能变

6. 列表转字符串

words = ["hello", "world", "python"]

# 用空格连接
s = " ".join(words)       # "hello world python"

# 用逗号连接
s = ",".join(words)       # "hello,world,python"

# 注意:join 只能连接字符串列表
nums = [1, 2, 3]
s = ",".join(map(str, nums))   # "1,2,3"

7. 字符串转列表

s = "hello world"

lst = s.split()            # ['hello', 'world']
lst = list(s)              # ['h', 'e', 'l', 'l', 'o', ' ', 'w', ...]
lst = s.split(",")         # 按逗号切

8. 切片赋值与删除

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

lst[1:3] = [10, 20]        # [1, 10, 20, 4, 5]
lst[1:3] = []              # 删除切片,[1, 4, 5]
del lst[1:3]               # 删除切片
lst[:] = [1, 2, 3]         # 替换整个列表内容

9. 复制列表

lst = [1, 2, 3]

# 浅拷贝
b = lst.copy()             # [1, 2, 3]
b = lst[:]                 # [1, 2, 3]
b = list(lst)              # [1, 2, 3]

# 注意:= 不是复制,是引用
c = lst                    # c 和 lst 是同一个列表
c.append(4)
print(lst)                 # [1, 2, 3, 4],lst 也被改了

浅拷贝 vs 深拷贝

import copy

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

shallow = copy.copy(nested)      # 浅拷贝,内层还是共享
deep = copy.deepcopy(nested)     # 深拷贝,完全独立

shallow[0].append(99)
print(nested)                    # [[1, 2, 99], [3, 4]],被影响

deep[0].append(100)
print(nested)                    # [[1, 2, 99], [3, 4]],不受影响

10. 条件筛选与转换:filtermap

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

# filter:筛选
evens = list(filter(lambda x: x % 2 == 0, nums))
# [2, 4]

# map:转换
squares = list(map(lambda x: x**2, nums))
# [1, 4, 9, 16, 25]

# 更推荐列表推导式
evens = [x for x in nums if x % 2 == 0]
squares = [x**2 for x in nums]

11. 列表作为栈和队列

栈(后进先出)

stack = []
stack.append(1)      # 入栈
stack.append(2)
stack.append(3)
print(stack.pop())   # 3,出栈
print(stack.pop())   # 2

队列(先进先出)

from collections import deque

queue = deque()
queue.append(1)       # 入队
queue.append(2)
queue.append(3)
print(queue.popleft())   # 1,出队
print(queue.popleft())   # 2

不要用 list 做队列,因为 pop(0) 是 O(n):

queue = [1, 2, 3]
queue.pop(0)          # O(n),效率低

12. 二维列表(矩阵)

# 创建 3x3 矩阵
matrix = [[0] * 3 for _ in range(3)]
# [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

# 访问
matrix[0][1] = 5
# [[0, 5, 0], [0, 0, 0], [0, 0, 0]]

# 转置
transposed = [[row[i] for row in matrix] for i in range(3)]

# 遍历
for row in matrix:
    for val in row:
        print(val)

经典坑:不要用 [[0] * 3] * 3 创建二维列表。

matrix = [[0] * 3] * 3
matrix[0][0] = 1
print(matrix)   # [[1, 0, 0], [1, 0, 0], [1, 0, 0]],三行共享同一个列表!

13. 列表作为函数参数

def add_item(lst, item):
    lst.append(item)

nums = [1, 2]
add_item(nums, 3)
print(nums)   # [1, 2, 3],原列表被修改

# 不想改原列表,传副本
add_item(nums[:], 4)
print(nums)   # [1, 2, 3],没变

经典坑:默认参数用可变对象。

def add_item(item, lst=[]):    # ❌
    lst.append(item)
    return lst

print(add_item(1))   # [1]
print(add_item(2))   # [1, 2],默认列表被共享了

正确写法:

def add_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

14. 列表排序的高级用法

# 按绝对值排序
nums = [-3, 1, -2, 4]
nums.sort(key=abs)          # [1, -2, -3, 4]

# 按字符串长度排序
words = ["apple", "hi", "banana"]
words.sort(key=len)         # ['hi', 'apple', 'banana']

# 按多个条件排序
students = [("小明", 25), ("小红", 20), ("小刚", 25)]
students.sort(key=lambda x: (x[1], x[0]))   # 先按年龄,再按名字

# 稳定排序
# Python 的 sort 是稳定的,相同 key 的元素保持原顺序

15. 列表的成员判断

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

print(3 in lst)         # True
print(10 not in lst)    # True

# 列表的 in 是 O(n),集合的 in 是 O(1)
# 频繁成员判断,先转 set
s = set(lst)
print(3 in s)           # O(1)

16. 列表的统计

lst = [1, 2, 2, 3, 3, 3]

print(len(lst))         # 6,长度
print(sum(lst))         # 14,求和
print(max(lst))         # 3,最大值
print(min(lst))         # 1,最小值
print(lst.count(3))     # 3,统计出现次数

# 平均值
avg = sum(lst) / len(lst)

17. 列表解包

# 基本解包
a, b, c = [1, 2, 3]

# 星号解包
first, *rest = [1, 2, 3, 4, 5]
# first = 1, rest = [2, 3, 4, 5]

*init, last = [1, 2, 3, 4, 5]
# init = [1, 2, 3, 4], last = 5

a, *mid, b = [1, 2, 3, 4, 5]
# a = 1, mid = [2, 3, 4], b = 5

18. 合并列表

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

# 方法一:+
c = a + b            # [1, 2, 3, 4],新列表

# 方法二:extend
a.extend(b)          # a 变成 [1, 2, 3, 4]

# 方法三:解包
c = [*a, *b]         # [1, 2, 3, 4]

# 方法四:itertools.chain
import itertools
c = list(itertools.chain(a, b))

19. 列表的 * 重复

[0] * 5              # [0, 0, 0, 0, 0]
[1, 2] * 3           # [1, 2, 1, 2, 1, 2]

经典坑:嵌套列表用 * 会共享引用。

matrix = [[0] * 3] * 3   # ❌ 三行是同一个列表
matrix[0][0] = 1
print(matrix)   # [[1, 0, 0], [1, 0, 0], [1, 0, 0]]

20. 列表推导式 + 条件表达式

# 偶数取平方,奇数取相反数
nums = [1, 2, 3, 4, 5]
result = [x**2 if x % 2 == 0 else -x for x in nums]
# [-1, 4, -3, 16, -5]

三、常见坑总结

说明正确做法
遍历时删元素会跳过元素遍历副本 lst[:] 或用推导式
[[0]*3]*3 创建二维三行共享引用[[0]*3 for _ in range(3)]
默认参数用 []被所有调用共享None 做默认值
b = a 以为是复制只是引用a.copy()a[:]
sort() 返回 None以为返回新列表sorted() 或直接 lst.sort()
浅拷贝嵌套列表内层还是共享copy.deepcopy()
列表做队列pop(0) 是 O(n)collections.deque
频繁 in 判断列表是 O(n)set

四、一句话总结

用法写法
创建[1,2,3]list(range(5))[x for x in ...]
appendinsertextend
popremovedelclear
lst[i] = x、切片赋值
索引、indexcountin
排序sort() 原地、sorted() 新列表
遍历带索引enumerate
同时遍历多个zip
去重保序list(dict.fromkeys(lst))
扁平化[x for sub in nested for x in sub]
append + pop
队列collections.deque
复制copy()[:]deepcopy()
拼接+extend[*a, *b]
解包a, *rest = lst

核心记住:list 是可变有序序列,增删改查是基础,列表推导式、enumerate、zip、dict.fromkeys 是经典。避开遍历时修改、二维列表共享引用、默认参数可变对象这几个大坑。