天天看点

shallow copy and deep copy(浅拷贝与深拷贝) -python

浅拷贝与深拷贝

    • 直接赋值
    • 浅拷贝
    • 深拷贝
    • 注:

首先先看一下copy的官方介绍:Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. This module provides generic shallow and deep copy operations (explained below).

意思就是: Python中的赋值语句不复制对象,它们在目标和对象之间创建绑定。 对于 可变或包含可变项的集合,有时需要一个副本,因此可以 更改一个副本而不更改另一个副本。 该模块提供了通用的浅层和深层复制操作(如下所述)。

后面所指父对象为容器,即存储数据的结构,子对象为数据

直接赋值

直接赋值相当于引用(别名)

shallow copy and deep copy(浅拷贝与深拷贝) -python

其父对象和子对象均指向指向同一个对象,下面对直接赋值进行增删改的测试

a = [1,2,3,4]
b = a
print(b) => [1,2,3,4]
#增加
a.append(5)
print(a,b) => [1,2,3,4,5]  [1,2,3,4,5]
#删除
del(a[0])
print(a,b) => [2,3,4,5]  [2,3,4,5]
#修改
a[-1] = 10
print(a,b) => [2,3,4,10]  [2,3,4,10]
           

同理,改变b也能够达到一样的效果,即直接赋值,无论做什么修改都会随着改变 (对容易的操作-增删 对数据的操作-修改)

浅拷贝

a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)

shallow copy and deep copy(浅拷贝与深拷贝) -python

进行增删改的测试

import copy
a = [1,2,3,4]
b = copy.copy(a)
print(a,b)  => [1,2,3,4] [1,2,3,4]
#增加
a.append(5)
print(a,b) => [1,2,3,4,5]  [1,2,3,4]
#删除
del(a[0])
print(a,b) => [2,3,4,5]  [1,2,3,4]
#修改
a[-1] = 10
print(a,b) => [2,3,4,10]  [1,2,3,4]
           

复合对象

import copy
a = [[1,2],3,4]
b = copy.copy(a)
print(a,b)  => [[1,2[,3,4] [[1,2],3,4]
#增加
a.append(5)
print(a,b) => [[1,2],3,4,5]  [[1,2],3,4]
#删除
del(a[2])
print(a,b) => [[1,2],3,5] [[1,2],3,4]
#修改
a[0][0] = 88
print(a,b) => [[88,2],3,5]  [[88,2],3,4]
           

可以看出,copy仅拷贝对象本身,不对其中的子对象进行拷贝,故对子对象的修改也会随着修改(针对嵌套的数据,即复合对象)

深拷贝

真正意义上的复制,即从新开辟一片空间

a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的

shallow copy and deep copy(浅拷贝与深拷贝) -python

浅拷贝与深拷贝的区别:

The difference between shallow and deep copying is only relevant for compound objects(仅与复合对象相关) (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

    经常存在深拷贝,但不存在浅拷贝的问题

    Two problems often exist with deep copy operations that don’t exist with shallow copy operations:

  • Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
  • Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.(用于共享的数据,造成空间浪费)

使用深拷贝的会避免以下问题

The deepcopy() function avoids these problems by:

  • keeping a memo dictionary of objects already copied during the current copying pass;
  • letting user-defined classes override the copying operation or the set of components copied.

注:

Shallow copies of dictionaries can be made using dict.copy(), and of lists by assigning a slice of the entire list, for example, copied_list = original_list[:].

可以使用dict.copy()和列表的浅层副本,通过分配整个列表的切片,例如,copied_list = original_list [:]。

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

此模块不复制类型,如模块,方法,堆栈跟踪,堆栈帧,文件,套接字,窗口,数组或任何类似类型。 它通过返回原始对象来“复制”函数和类(浅和深); 这与pickle模块处理这些方式兼容。

官方链接

https://docs.python.org/3/library/copy.html