1. 程式人生 > >Python 深拷貝、淺拷貝

Python 深拷貝、淺拷貝

地址 pre 產生 字典 deep 可能 新的 之間 append

Python中,對象的賦值,拷貝(深/淺拷貝)之間是有差異的,如果使用的時候不註意,就可能產生意外的結果。

首先,對賦值操作我們要有以下認識:

  1. 賦值是將一個對象的地址賦值給一個變量,讓變量指向該地址( 舊瓶裝舊酒 )。
  2. 修改不可變對象(strtuple)需要開辟新的空間
  3. 修改可變對象(list等)不需要開辟新的空間

淺拷貝

? 淺拷貝僅僅復制了容器中元素的地址,就是拷貝了引用,並沒有拷貝內容。

In [1]: a = [11,22,33]

In [2]: id(a)
Out[2]: 22132096

In [3]: b = a

In [4]: id(b)
Out[4]: 22132096
# 引用相同 In [5]: a.append(44) In [6]: a Out[6]: [11, 22, 33, 44] In [7]: b Out[7]: [11, 22, 33, 44] # b的值也變化

深拷貝

深拷貝是對於一個對象所有層次的拷貝(遞歸)

In [8]: import copy

In [9]: a = [11, 22, 33]

In [10]: id(a)
Out[10]: 74598640

In [11]: b = copy.deepcopy(b)

In [12]: id(b)
Out[12]: 79142624

In [13]: a.append(44
) In [14]: a Out[14]: [11, 22, 33, 44] In [15]: b Out[15]: [11, 22, 33, 44]

進一步理解

In [23]: a = [11,22,33]

In [24]: b = [44,55,66]

In [25]: c = (a,b)

In [26]: e = copy.deepcopy(c)

In [27]: a.append(77)

In [28]: a
Out[28]: [11, 22, 33, 77]

In [29]: b
Out[29]: [44, 55, 66]

In [30]: c
Out[30]: ([11
, 22, 33, 77], [44, 55, 66]) In [31]: e Out[31]: ([11, 22, 33], [44, 55, 66]) # copy.copy()方法 In [32]: f = copy.copy(c) In [33]: a.append(88) In [34]: a Out[34]: [11, 22, 33, 77, 88] In [35]: b Out[35]: [44, 55, 66] In [36]: c Out[36]: ([11, 22, 33, 77, 88], [44, 55, 66]) In [37]: e Out[37]: ([11, 22, 33], [44, 55, 66]) In [38]: f Out[38]: ([11, 22, 33, 77, 88], [44, 55, 66])

拷貝的其他方式

淺拷貝對不可變類型和可變類型的copy不同
In [88]: a = [11,22,33]

In [89]: b = copy.copy(a)

In [90]: id(a)
Out[90]: 59275144

In [91]: id(b)
Out[91]: 59525600

In [92]: a.append(44)

In [93]: a
Out[93]: [11, 22, 33, 44]

In [94]: b
Out[94]: [11, 22, 33]


In [95]: a = (11,22,33)

In [96]: b = copy.copy(a)

In [97]: id(a)
Out[97]: 58890680

In [98]: id(b)
Out[98]: 58890680
  • 分片表達式可以賦值一個序列
    a = "abc"

    b = a[:]
  • 字典的copy方法可以拷貝一個字典
    d = dict(name="zhangsan", age=27)

    co = d.copy()
  • 有些內置函數可以生成拷貝(list)
    a = list(range(10))

    b = list(a)
  • copy模塊中的copy函數
    import copy

    a = (1,2,3)

    b = copy.copy(a)

Python 深拷貝、淺拷貝