【问题标题】:Why does shallow copy behaves as deep copy for a simple list为什么浅拷贝的行为与简单列表的深拷贝一样
【发布时间】:2020-03-20 09:25:35
【问题描述】:

我正在理解 python 中的浅拷贝和深拷贝概念。我观察到大部分posts/blogs/SO answer 解释这些概念都是使用嵌套列表。

import copy
lst = [[1,2,3],[4,5,6]]
b = copy.copy(lst)
c = copy.deepcopy(lst)

# Shallow copy demo
b[0][0] = 9
print(b)
# >>> [[9, 2, 3], [4, 5, 6]]
print(lst)    
# >>> [[9, 2, 3], [4, 5, 6]]

# Deepcopy demo
c[0][0] = 10
print(c)
# >>> [[10, 2, 3], [4, 5, 6]] 
print(lst)
# >>> [[9, 2, 3], [4, 5, 6]]

通过上面的简单示例,我理解了浅拷贝和深拷贝的概念。但是当我实现这个概念时,在一个简单的列表(一维列表)上,观察到的是浅拷贝表现得像深拷贝。

import copy
lst = [1,2,3]
b = copy.copy(lst)
c = copy.deepcopy(lst)

# Shallow copy demo
b[0] = 0
print(b)
# >>> [0, 2, 3]
print(lst)
# >>> [1,2,3]

# Deepcopy demo
c[0] = 9
print(c)
# >>> [9,2,3]
print(lst)
# >>> [1,2,3]

这表明copy.copy(lst) 的行为有所不同,它进行的是深拷贝而不是浅拷贝。

我想了解,为什么 copy.copy() 的行为对于嵌套列表和简单列表是不同的。另外,如果我必须让浅拷贝为简单列表工作,我该如何实现?

【问题讨论】:

  • 'Shallow' vs. 'deep' 仅在数据结构的深度超过一个级别时才重要。您的整数列表并非如此。
  • @jasonharper,感谢您的说明。

标签: python-3.x deep-copy shallow-copy


【解决方案1】:

你得到的结果与“深度”没有直接关系, 这里要记住的最重要的事情是可变性的概念。

列表是可变的,而数值不是。这意味着您可以添加或修改列表中的项目,但这些操作不会创建或销毁列表,它们只会更改它。您可以使用内置函数id() 进行验证,它会为您提供变量的内存地址:

lst = [1, 2, 3]
print(id(lst)) # the number printed by this...
lst.append(4)
lst[1] = 0
print(id(lst)) # should be the same printed by this one. That tells us that 
               # the variable 'lst' keeps referecing the same object, although
               # the object have changed in form (mutated)

数字是完全不同的,这是有道理的,因为数字类型的变量只能 存储单个数值:

a = 5
print(id(a)) # the number printed by this...
a = 6
print(id(a)) # should be different than this one, meaning that a new numeric 
             # value were created and stored in a different memory address

上线

b[0][0] = 9

在您的第一个示例中,b[0] 的列表正在被操作,但它仍然是同一个对象,并且由于 b[0] 只不过是对 lst[0] 的同一列表的引用(因为 b是浅拷贝),当我们打印 lst 时,我们会看到它也发生了变化。

在您的实现中,当您分配 b[0] = 0 时,python 正在创建值 0,将其存储在新的内存位置,并覆盖 b[0] 必须与 lst[0] 具有相同值的引用(因为这是数字类型的自然行为)。

如前所述,这不一定与复合数据结构的嵌套级别有关, 因为其中一些是不可变的(例如元组),并且在您的实现中发生的相同情况也会发生在这种不可变的数据结构中。

您可以阅读更多关于 id() 内置函数 here 的信息,以及更多关于 可变和不可变类型here

希望这个答案对你有所帮助!

【讨论】:

    猜你喜欢
    • 2011-02-09
    • 2022-01-15
    • 2012-04-12
    • 2015-01-13
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多