跳到主要内容

拷贝、引用与可变对象

这类问题在 Python 初学阶段出现频率非常高:为什么我改了 new_listoriginal_list 也跟着变了?

原因通常不是“列表很奇怪”,而是你拿到的是同一个对象的引用。

赋值不是拷贝

original = [1, 2, 3]
new_list = original

new_list.append(4)

print(original) # [1, 2, 3, 4]
print(new_list) # [1, 2, 3, 4]

new_list = original 做的事不是复制列表,而是让两个变量指向同一个列表对象。

浅拷贝

下面这些方式都会创建新的外层列表:

items = [1, 2, 3]

a = items[:]
b = list(items)
c = items.copy()

但它们只复制一层

items = [[1, 2], [3, 4]]
copied = items.copy()

copied[0].append(99)

print(items) # [[1, 2, 99], [3, 4]]
print(copied) # [[1, 2, 99], [3, 4]]

因为外层列表虽然是新的,里面嵌套的子列表仍然指向同一批对象。

深拷贝

如果对象内部还有嵌套结构,就要考虑 copy.deepcopy()

import copy

items = [[1, 2], [3, 4]]
copied = copy.deepcopy(items)

copied[0].append(99)

print(items) # [[1, 2], [3, 4]]
print(copied) # [[1, 2, 99], [3, 4]]

为什么这件事重要

因为 Python 里很多对象都是可变的:

  • list
  • dict
  • set

如果你没有分清“我是在改原对象”还是“我是在改副本”,后面调试会非常痛苦。

我自己的判断方式

  • 只写了 a = b:基本不是拷贝
  • 只复制了最外层:浅拷贝
  • 里面还有嵌套,且想完全独立:深拷贝

关联阅读