Python中修改切片得到的列表副本不会改变原列表的原因是什么
Python列表切片可变性问题解答
核心结论:你观察到的现象是Python列表切片的默认行为导致的,对Python列表执行[start:end]切片操作时,会生成一个新的独立列表实例(属于浅拷贝),而非原列表的视图引用。如果你有R语言背景,这个逻辑和R中切片返回新向量副本的行为是一致的,和你第一部分直接赋值别名的逻辑完全不同。
接下来对应你的代码逻辑逐一解释:
1. 第2部分现象的本质
你执行listSlice = listOrig[0:5]后,内存中会生成一个全新的列表容器,这个新容器的前5个元素的引用,和原列表listOrig前5个元素的引用完全相同——所以你测试listOrig[0] is listSlice[0]会返回True,因为两个不同列表的对应位置指向了同一个整数999的实例。
你可以补充一行代码验证两个列表本身是独立的:
listOrig is listSlice # 返回False,证明二者是存储在不同内存地址的不同列表实例
2. 第3部分现象的原因
当你执行listSlice[0] = 1001时,你修改的是新生成的切片列表这个独立容器的第0位引用:相当于让切片列表的第0位,从原来指向999的实例,改成指向新的1001实例。这个操作全程没有修改原列表listOrig的任何元素引用,所以原列表自然不会受到影响。
补充:和第一部分赋值操作的区别
你第一部分执行listCopy = listOrig时,没有生成新的列表容器,只是给内存中已有的原列表实例新增了一个别名,两个变量指向的是完全同一个列表。所以你修改任意一个变量指向的列表的元素,本质都是修改同一个容器的内容,另一个变量自然会同步感知到变化。
额外拓展:浅拷贝的特性
这里的切片属于浅拷贝,仅复制最外层的列表容器。如果原列表中存储的是可变对象(比如子列表、字典),你修改可变对象的内部内容时,原列表和切片列表会同步变化:
listA = [[1], 2, 3] listB = listA[:] # 修改内层可变对象的内容,原列表和切片列表都会变 listB[0][0] = 999 print(listA[0][0]) # 输出999,因为内层的子列表引用是共享的 # 修改外层容器的引用,二者互不影响 listB[0] = 1000 print(listA[0][0]) # 还是999,listA不受影响
内容的提问来源于stack exchange,提问作者Spaniel
相关产品推荐
相关产品推荐

