Python列表切片修改疑问:新列表修改为何不影响原列表?
关于Python列表切片修改与浅拷贝的疑问解答
嘿,让我一步步拆解你的两个问题,结合你的代码和输出把事情说清楚:
问题1:修改Python列表的切片时会发生什么?
分两种核心情况:
- 如果你直接对原列表的切片做赋值(比如
A[1:3] = [10, 20]),这会直接修改原列表的对应位置——切片在这里相当于原列表的一个“视图”,赋值操作会替换原列表中该切片范围内的元素。 - 但如果是把切片赋值给新变量(比如
B = A[:]),这其实是创建了原列表的浅拷贝:新列表B和原列表A是两个独立的容器,但它们初始会共享对元素的引用。
问题2:为什么修改B的元素不影响A?
先看你的输出:一开始A和B的元素内存地址确实相同,这是因为浅拷贝复制的是元素的引用,不是元素本身。那为啥修改B后A没变化?核心原因是:你做的是重新赋值元素,而非修改元素本身的内容。
咱们掰碎了说:
- 整数是Python里的不可变对象,你没法修改一个整数的内容(比如把0变成12345),所谓的“修改”其实是创建一个新的整数对象,然后让列表的对应位置指向这个新对象。
- 你执行
B[i] = 12345时,只是把B列表第i个位置的引用,从原来指向0/1/2等旧整数的地址,改成了指向新整数12345的地址。而A列表的第i个位置,依然牢牢指向原来的旧整数,所以A的内容完全不受影响。
如果你的列表里装的是可变对象(比如嵌套列表),情况就不一样了:比如A = [[1], [2]],B = A[:],这时候你修改B[0][0] = 10,A的内容也会变成[[10], [2]]——因为你修改的是可变对象内部的内容,而不是给列表元素重新赋值引用,这时候两个列表共享的可变对象被修改,自然都会体现变化。
再回头看你的代码:
def printAddresses(A): for i in range(len(A)): print(f"memory address of list element {i}: {hex(id(A[i]))}") print("\n\n\n") A = list(range(5)) B = A[:] print("addresses of elements of A") printAddresses(A) print("addresses of elements of B") printAddresses(B) for i in range(len(B)): B[i]=12345 print("A: ", A) print("B: ", B)
输出里初始元素地址相同,是因为B的每个元素都引用了A里的同一个整数。但赋值12345后,B的元素引用指向了新对象,A的还是旧的,所以结果才会A不变、B全变成12345。
你忽略的关键点就是:
A[:]是浅拷贝,两个列表独立,但共享不可变元素的引用;- 对不可变元素的“修改”本质是重新赋值引用,不会影响另一个列表;只有修改可变对象的内部内容时,才会让两个列表同步变化。
内容的提问来源于stack exchange,提问作者Alex Armbruster
相关产品推荐
相关产品推荐

