如何克隆列表以避免赋值后意外更改
如何克隆列表以避免赋值后意外更改
技术背景
在Python中,直接使用 new_list = my_list
进行赋值操作时,实际上并没有创建一个新的列表。这种赋值只是复制了列表的引用,而不是实际的列表对象。因此,赋值后 new_list
和 my_list
都指向同一个列表,对其中一个列表的修改会影响另一个列表。为了避免这种情况,需要真正地复制列表。
实现步骤
浅拷贝
浅拷贝只复制列表本身,即列表中对象的引用,而不复制对象本身。如果列表中的对象是可变的,对这些对象的修改会同时反映在原列表和浅拷贝的列表中。
- Python 2:
- 使用切片操作:
a_copy = a_list[:]
- 使用
list
构造函数:a_copy = list(a_list)
- 使用切片操作:
- Python 3:
- 使用
list.copy()
方法:a_copy = a_list.copy()
- 使用
深拷贝
深拷贝会递归地复制列表中的所有对象,创建一个完全独立的新列表。即使原列表中的对象是可变的,对深拷贝列表的修改也不会影响原列表,反之亦然。使用 copy
模块的 deepcopy
函数:
1 |
|
核心代码
浅拷贝示例
1 |
|
深拷贝示例
1 |
|
最佳实践
- 对于简单列表(列表中的元素都是不可变对象):使用切片操作
list[:]
或list.copy()
方法进行浅拷贝,因为它们速度快且代码简洁。 - 对于嵌套列表或包含可变对象的列表:使用
copy.deepcopy()
进行深拷贝,以确保复制的列表与原列表完全独立。
常见问题
直接赋值的问题
1 |
|
直接赋值只是复制了引用,new_list
和 my_list
指向同一个列表,对 new_list
的修改会影响 my_list
。
浅拷贝对嵌套列表的问题
1 |
|
浅拷贝只复制了外层列表,内层列表的引用仍然相同,对嵌套列表的修改会同时影响原列表和浅拷贝的列表。
不建议使用 eval
进行深拷贝
1 |
|
eval
方法不仅危险(如果评估的内容来自不可信的源),而且不可靠(如果要复制的子元素没有可用于 eval
以重现等效元素的表示形式),并且性能较差。
如何克隆列表以避免赋值后意外更改
https://119291.xyz/posts/2025-05-09.how-to-clone-a-list-to-avoid-unexpected-changes-after-assignment/