Python列表切片修改不影响原列表的原因及同步修改实现方法
问题解答
为什么原列表a没有同步被修改
首先纠正一个认知误区:普通Python列表的切片操作得到的新列表,元素确实和原列表的元素引用同一个对象,本次没有同步修改的核心原因和操作类型、元素类型有关:
你执行的b[0] = 0是对b列表的第0位做重新赋值操作,本质是把b的第0位指针从原来指向整数1,修改为指向新的整数0。而整数属于Python的不可变类型,你无法修改整数1本身的值,这个重新赋值的操作仅修改了b列表自身的指针指向,完全没有触及原列表a的指针,因此a不会发生变化。
你可以用可变类型元素做个验证:
a = [[1], 2, 3] b = a[:2] b[0][0] = 0
此时a的结果会变成[[0], 2, 3],这就是因为你修改的是b[0]指向的可变列表对象本身,而不是给b[0]重新赋值,所以和它引用同一个对象的a[0]也会同步变化。
如何实现修改b时a同步更新
Python原生的列表没有切片视图的能力,切片默认执行浅拷贝,如果你要实现该效果,最常用的方案是使用NumPy数组,NumPy的切片默认返回原数组的视图,不会创建新的拷贝,修改视图会同步修改原数组:
import numpy as np a = np.array([1, 2, 3]) b = a[:2] b[0] = 0
运行后a的值为array([0, 2, 3]),b的值为array([0, 2]),完全符合需求。
如果不想引入NumPy依赖,也可以自定义封装列表类,维护切片和原列表的引用关系,但实现复杂度较高,常规场景下优先推荐NumPy方案。
内容的提问来源于stack exchange,提问作者Ignas Nevinskas
相关产品推荐
相关产品推荐

