Day2 Python List 操作的细节

29 阅读3分钟

在 Python 中,列表(List)是最常用的数据结构之一。它既可以存储任意类型的数据,又支持动态扩展。在日常开发中,很多逻辑都离不开列表操作。不过,一些看似简单的用法,往往隐藏着容易忽略的问题。

基础操作

  1. 增加元素
lst = [1, 2, 3]    

lst.append(4)      # 末尾添加
lst.insert(1, 10)  # 指定位置插入

print(lst)  # [1, 10, 2, 3, 4]
  • append:始终加在最后
  • insert:需要指定索引位置
  1. 删除元素
lst = [1, 2, 3, 4]

a = lst.pop()      # 删除最后一个
print(a)  # 4

lst.pop(1)     # 删除指定位置
print(lst)  # [1, 3]

注意:pop 会返回被删除的元素,这在某些场景中很有用。

  1. 修改元素
lst = [1, 2, 3]

lst[0] = 100
print(lst)  # [100, 2, 3]

注意:上一篇我们说到 list 是可变数据类型,内容可以被直接修改。

  1. 查询与切片
lst = [1, 2, 3, 4, 5]

print(lst[0])      # 1
print(lst[1:4])    # [2, 3, 4]
print(lst[::-1])   # 反转列表
切片形式参数含义
Ist[i]第一个元素位置为0访问单个元素
Ist[start:stop]start : 起始索引(包含)stop : 结束索引(不包含)从 start 到 stop-1
Ist[start:stop:step]start:若省略,默认为列表末尾;stop:若省略,默认为列表开头;step:若step为负数时,从右向左遍历,若为 -1,表示从后往前遍历带step的切片

列表推导式

当你需要对列表做批量处理时,列表推导式会让代码更简洁。

lst = [1, 2, 3, 4]

# 每个元素平方
new_lst = [x * x for x in lst]

print(new_lst)  # [1, 4, 9, 16]

带条件过滤,写法:[表达式 for 变量 in 可迭代对象 if 条件]

# 列表推导式,只保留偶数
even_lst = [x for x in lst if x % 2 == 0]
print(even_lst)  # [2, 4]

# 传统写法
result = []
for x in lst:
    if x % 2 == 0:
        result.append(x)

列表推导式是Python的"语法糖",比传统循环快30-50%,代码也更优雅。

列表常见错误

  1. 复制列表
a = [1, 2, 3]
b = a  # 不是复制,而是引用

b.append(4)

print(a)  # [1, 2, 3, 4]

这里的 b = a 并没有创建新列表,而是指向同一块内存。

正确做法:

b = a.copy()
# 或
b = a[:]
  1. 嵌套列表的引用
lst = [[0] * 3] * 3

lst[0][0] = 1
print(lst)  # [[1, 0, 0], [1, 0, 0], [1, 0, 0]]

上述代码拆解:

  1. [0] * 3 → 创建列表 [0, 0, 0]
  2. [[0] * 3] → 创建包含一个子列表的列表 [[0, 0, 0]]
  3. [[0] * 3] * 3 → 复制 3 次,得到 [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

而* 运算符对列表进行复制时,是 浅拷贝 ,只复制引用,不创建新对象!即 lst[0]lst[1]lst[2] 都指向同一个列表对象。因此执行 lst[0][0] = 1 后所有子列表的第一个元素都会变成 1。

正确写法:

lst = [[0] * 3 for _ in range(3)]   #循环只需要执行 3 次,不需要使用循环变量

lst[0][0] = 1
print(lst)  # [[1, 0, 0], [0, 0, 0], [0, 0, 0]]

拆解:

  1. 第1次循环: [0] * 3 → 创建新列表 [0, 0, 0] → 存入 lst[0]
  2. 第2次循环: [0] * 3 → 创建新列表 [0, 0, 0] → 存入 lst[1]
  3. 第3次循环: [0] * 3 → 创建新列表 [0, 0, 0] → 存入 lst[2]

即,每次循环都会创建一个全新的列表对象,互不影响。

总结

列表看起来简单,但在复杂逻辑中,很容易因为引用关系引发问题。理解这一点,对后续学习数据结构和内存模型也有帮助。