天天看點

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