Python列表+=运算符异常行为:帕斯卡三角代码问题
问题解析:Python中
+=运算符与列表初始化的陷阱 问题场景
以下代码原本可以正确生成帕斯卡三角的前N行:
N = 5 L = [[]] * N i = j = 0 while i < N: if j == 0 or j == i: a = 1 else: a = L[i-1][j] + L[i-1][j-1] L[i] = L[i] + [a] # 这一行正常工作 if j < i: j += 1 else: j = 0 i += 1 [print(x) for x in L]
输出结果:
[1] [1, 1] [1, 2, 1] [1, 3, 3, 1] [1, 4, 6, 4, 1]
但将标记行替换为L[i] += [a]后,代码失效——所有子列表都会被追加[a],而非仅修改L[i]。
而下面的简单示例却运行正常:
L = [[], []] L[0] += [1] L[1] += [2] print(L)
输出:[[1], [2]]
核心原因解析
1. [[]] * N的本质:共享同一列表对象
当你用L = [[]] * N初始化列表时,并不是创建N个独立的空列表,而是创建了一个包含N个指向同一个空列表对象的引用的列表。也就是说,L[0]、L[1]……L[N-1]其实都是同一个列表的别名,修改其中任何一个,其他的都会跟着变。
而第二个简单示例中,L = [[], []]是直接创建了两个独立的空列表对象,所以修改其中一个不会影响另一个。
2. +=与+的行为差异
L[i] = L[i] + [a]:这个操作先计算L[i] + [a],生成一个新的列表对象,然后把L[i]的引用指向这个新列表。此时L[i]不再指向原来的共享列表,后续修改也只会影响这个新列表,所以帕斯卡三角的代码能正常工作。L[i] += [a]:这个操作是调用列表的extend()方法(+=对于列表是原地修改操作),直接在原列表对象上追加元素。因为L[i]指向的是那个被所有子列表共享的原空列表,所以这个原地修改会让所有L中的子列表都看到变化,导致所有子列表都被追加了元素。
验证与解决方法
如果要避免这个问题,初始化列表时应该创建N个独立的空列表,比如:
L = [[] for _ in range(N)]
这样每个子列表都是独立的对象,无论用+=还是+赋值,都只会修改对应的子列表。
内容的提问来源于stack exchange,提问作者Luiz Eleno
相关产品推荐
相关产品推荐

