1. 程式人生 > 其它 >python中深淺複製教程

python中深淺複製教程

在python中,等號作用是引用物件地址對應的物件

python中的資料分為可變型別和不可變型別:

  • 可變型別:可列表、字典
  • 不可變資料型別:字串String、浮點型Float、整型Int、元祖Tuple。

對於不可變型別資料來說,其記憶體地址是不變的

# 比如:
id(3)  # 通過id檢視資料記憶體地址
# 輸出:
    140708771369856

# 再次檢視3的記憶體地址,可以看到和上一個3的記憶體地址是一樣
id(3)
# 輸出:
    140708771369856

對於可變型別資料,其記憶體地址是不固定的

其extend、append、+=等操作會使得其地址對應的資料發生變化。

# 比如:
id([1, 2])
# 輸出:
    2204932119304

# 再次檢視同樣的資料,可以看到其記憶體地址已變化
id([1, 2])
# 輸出:
    2204931521416

# 所以,對於不可變型別資料,深複製和淺複製都一樣,沒有什麼影響
a = 3
b = a
print(f'a={a}, a記憶體地址:{id(a)}\nb={b}, b記憶體地址:{id(b)}')
# 輸出:
    a=3, a記憶體地址:140708771369856
    b=3, b記憶體地址:140708771369856

對於可變型別資料

  • 不同的可變資料物件,即使數值相等,其記憶體地址也不相等
  • 如果要引用其他物件的值,最好使用深複製或淺複製
# 若不進行深複製或淺複製:
a = [1, 2, 3, ['a', 'b']]
b = a
print(f'a: {a}\na記憶體地址:{id(a)}\nb: {b}\nb記憶體地址:{id(b)}')
print('*' * 20)
# 改變a的值
a += b  # a的記憶體地址不變,但是資料變了。注:這裡的變只是對於類似於append、+=、extend等這種操作。若是直接賦值,比如a=[0, 6]這樣是不會影響的。
print(f'a: {a}\na記憶體地址:{id(a)}\nb: {b}\nb記憶體地址:{id(b)}')

# 輸出:
    a: [1, 2, 3, ['a', 'b']]
    a記憶體地址:2204931464136
    b: [1, 2, 3, ['a', 'b']]
    b記憶體地址:2204931464136
    ********************
    a: [1, 2, 3, ['a', 'b'], 1, 2, 3, ['a', 'b']]
    a記憶體地址:2204931464136
    b: [1, 2, 3, ['a', 'b'], 1, 2, 3, ['a', 'b']]
    b記憶體地址:2204931464136

淺複製

  • 在python2中需要 import copy
  • python3中可以直接使用copy(),但是deepcopy()方法還需要匯入模組
  • copy()方法稱為淺複製, deepcopy()方法稱為深複製
  • 淺複製是複製了新的物件,和原物件公共引用資料地址。

建議:在記憶體足夠的情況下,選擇深拷貝,這樣邏輯處理獨立,不會產生上下文的影響,不容易發生難以解決的bug。

情況1:

a = [1, 2, 3, ['a', 'b']]
b = a.copy()  # 淺複製
a += b  # 改變a,對b的值沒有影響
print(f'a: {a}\na記憶體地址:{id(a)}\nb: {b}\nb記憶體地址:{id(b)}')

# 輸出:
    a: [1, 2, 3, ['a', 'b'], 1, 2, 3, ['a', 'b']]
    a記憶體地址:2204931416328
    b: [1, 2, 3, ['a', 'b']]
    b記憶體地址:2204932131208

情況2:

'''
學習中遇到問題沒人解答?小編建立了一個Python學習交流群:725638078
尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視訊學習教程和PDF電子書!
'''
a = [1, 2, 3, ['a', 'b']]
b = a.copy()
print(f'a: {a}\na記憶體地址:{id(a)}\nb: {b}\nb記憶體地址:{id(b)}')
print('*' * 20)
a += b
a[3] += ['d', 'e']  # 改變a,對b的值產生影響了,這是因為b
print(f'a: {a}\na記憶體地址:{id(a)}\nb: {b}\nb記憶體地址:{id(b)}')

# 輸出:
    a: [1, 2, 3, ['a', 'b']]
    a記憶體地址:2204931366024
    b: [1, 2, 3, ['a', 'b']]
    b記憶體地址:2204931363976
    ********************
    a: [1, 2, 3, ['a', 'b', 'd', 'e'], 1, 2, 3, ['a', 'b', 'd', 'e']]
    a記憶體地址:2204931366024
    b: [1, 2, 3, ['a', 'b', 'd', 'e']]
    b記憶體地址:2204931363976

深複製

  • 在淺複製的情景2中,改變a中巢狀的列表,同樣會使得b的值產生變化。
  • 為了避免這種情況產生,如果記憶體滿足要求情況下,儘量使用深複製。
  • 深複製是完全生成新的物件,引用的是新的記憶體地址,兩個資料間完全沒有聯絡。
import copy

a = [1, 2, 3, ['a', 'b']]
b = copy.deepcopy(a)
a += b
a[3] += ['d', 'e']
print(f'a: {a}\na記憶體地址:{id(a)}\nb: {b}\nb記憶體地址:{id(b)}')

# 輸出:
    a: [1, 2, 3, ['a', 'b', 'd', 'e'], 1, 2, 3, ['a', 'b']]
    a記憶體地址:2204930530952
    b: [1, 2, 3, ['a', 'b']]
    b記憶體地址:2204930530568

結尾給大家推薦一個非常好的學習教程,希望對你學習Python有幫助!

Python基礎入門教程推薦

Python爬蟲案例教程推薦