Python列表链式赋值两种结果的底层运行原理探究
Python链式赋值导致两种列表差异的底层原因
首先明确Python链式赋值的核心规则:先计算右侧表达式的值,再从左到右依次将该值赋值给左侧的每个目标。下面拆解两个场景的差异:
场景1:x = x[1] = [1, 2]生成无限列表
执行步骤:
- 先创建列表对象
[1, 2],记为L(此时L的内容是[1,2],内存中是独立对象)。 - 第一个赋值:
x = L,变量x指向列表L。 - 第二个赋值:
x[1] = L,也就是把列表L本身的引用赋值给L的索引1位置。这时候L的第二个元素不再是原来的2,而是指向L自己,形成了递归引用——列表里的元素引用列表本身,所以Python显示时会用[...]表示无限递归结构,最终得到[1, [...]]。
场景2:x = x[1:] = [1, 2]生成普通列表
执行步骤:
- 同样先创建列表对象
[1, 2],记为M。 - 第一个赋值:
x = M,变量x指向列表M,此时M内容为[1,2]。 - 第二个赋值:
x[1:] = M,这是切片赋值操作,和单个索引赋值逻辑完全不同:切片赋值会把右侧可迭代对象(这里是M)的元素逐个展开后,替换左侧切片对应的位置。x[1:]对应的是x中从索引1到末尾的部分,也就是原来的[2]。- 把这部分替换成
M的元素1和2,所以最终x的内容变成[1] + [1,2],也就是[1,1,2]。
核心差异总结
- 单个索引赋值(
x[1] = ...):直接将右侧对象的引用赋值给列表指定位置,若赋值的对象是列表本身,就会形成自引用的无限列表。 - 切片赋值(
x[1:] = ...):将右侧可迭代对象的元素展开后替换切片区域,不会直接赋值对象本身,因此不会产生递归引用。
内容的提问来源于stack exchange,提问作者sn_2022
相关产品推荐
相关产品推荐

