【问题标题】:Why there is no difference between shallow copy and deep copy for a list of immutables为什么不可变列表的浅拷贝和深拷贝没有区别
【发布时间】:2014-07-06 23:20:31
【问题描述】:

假设我有一个由immutables.组成的python列表l当我在做一个浅拷贝和一个深拷贝时,结果是一样的:

>>> a = (1,2) # immutable types
>>> b = (3,4)
>>> l = [a,b] # a list containing immutable types

>>> import copy
>>> y = copy.copy(l) # shallow copy
>>> z = copy.deepcopy(l) # deep copy

>>> id(l[0])
139857440375584
>>> id(y[0])
139857440375584
>>> id(z[0])
139857440375584 # all have the same id's , so all refer to the same object

这是否意味着浅拷贝深拷贝只对mutable类型的集合有意义,因为immutable类型永远不会改变。 但是,如果我们想为这些类型的集合实现类似深拷贝的行为,我们该怎么做呢?

问候。

【问题讨论】:

  • 所有对不可变对象的引用总是有类似深拷贝的行为(如果你复制,你永远不会看到对原始对象的更改反映在其中)。
  • @thatotherguy 这两个集合会有不同的 'ids` 并且它们的元素的 'ids' 也会不同,意味着完全重复。
  • 所以你只是想看看内部 id 的变化,而不关心复制的语义?
  • @thatotherguy,我理解语义。集合的浅表副本是集合结构的副本,而不是元素的副本。使用浅拷贝,两个集合现在共享单个元素。深拷贝复制一切。一个集合的深层副本是两个集合,其中原始集合中的所有元素都是重复的。
  • @thatotherguy,你说“所有对不可变对象的引用总是有类似深拷贝的行为”。我猜它应该是类似浅拷贝的行为。

标签: python python-2.7 python-3.x deep-copy python-internals


【解决方案1】:

由于您无法更改不可变对象,因此在复制时创建相同对象的副本毫无意义。

浅拷贝

根据copy's source code,不可变类型的浅拷贝是这样完成的

def _copy_immutable(x):
    return x

for t in (type(None), int, long, float, bool, str, tuple,
          frozenset, type, xrange, types.ClassType,
          types.BuiltinFunctionType, type(Ellipsis),
          types.FunctionType, weakref.ref):
    d[t] = _copy_immutable

对于所有不可变类型,_copy_immutable 函数在浅拷贝期间按原样返回对象。

深拷贝

同样,在元组的深度复制期间,对象按原样返回,根据_deepcopy_tuple function

d = id(x)
try:
    return memo[d]

【讨论】:

    【解决方案2】:

    thefourtheye 解释了为什么没有区别。如果你无论如何都想这样做,你可以通过酸洗来混合它:

    import pickle
    
    a = (1,2)
    b = (3,4)
    l = [a,b]
    
    z = pickle.loads(pickle.dumps(l))
    
    print id(l[0])
    print id(z[0])
    

    显然,这绝不是必要的。

    【讨论】:

    • 谢谢,非常有帮助的答案。为它 +1。
    【解决方案3】:

    对于这种特定情况,优化了创建小整数对象。即使做一个简单的赋值,你也可以观察到对象的相同标识,即使它们不应该互相认识:

    >>> a = 1
    >>> b = 5
    >>> c = 1
    >>> d = 5
    >>> id(a)
    1815461288
    >>> id(c)
    1815461288
    >>> id(b)
    1815461352
    >>> id(d)
    1815461352
    

    【讨论】:

      猜你喜欢
      • 2010-09-16
      • 1970-01-01
      • 2016-05-07
      • 2012-04-12
      • 2023-04-05
      • 2013-06-19
      • 2015-01-13
      相关资源
      最近更新 更多