Python和Numpy中——淺拷貝和深拷貝的詳解

Python—淺拷貝和深拷貝的詳解

首先我們要了解一下淺拷貝和深拷貝的概念:

1.淺拷貝

定義:淺拷貝是對另外一個變量的內存地址的拷貝,這兩個變量指向同一個內存地址的變量值。

注:僅僅拷貝的是目標變量的所在地址,目標變量的所在地址不發生任何變化。

實際上,變量中並沒有存儲任何的值,它只是指向了一個內存地址,而這個地址裏存儲着具體的內容,例如把變量a賦值給變量b的時候,實際上是把a指向內存中某對象的鏈接賦給了b,也就是說,現在a和b都指向了同一個對象。因此,在改變了內存中array的值後,而a與b都引用了該array對象,所以都一起發生了變化

淺拷貝的特點:

  • 公用一個值;
  • 這兩個變量的內存地址一樣;
  • 對其中一個變量的值改變,另外一個變量的值也會改變;

2.深拷貝

定義:一個變量對另外一個變量的拷貝。

注:拷貝的是目標變量的值,是真實的拷貝,新的變量產生了新的內存地址。

深拷貝的特點:

  • 變量的內存地址不同;
  • 變量各有自己的值,且互不影響;
  • 對其任意一個變量的值的改變不會影響其餘變量的值;

3. Python中表(List)數據中

  • 直接賦值給另一個變量是 淺拷貝

  • 切片操作 是 深拷貝

    #Python中的淺拷貝
    a = [1,2,3,4,5,6]
    b = a #a直接賦值b
    print('a的初始內存地址:',id(a))
    print('b的初始內存地址:',id(b))
    b.append(7)#對b尾部加數字7
    print('a:',a)
    print('b:',b)
    print('a的當前內存地址:',id(a))
    print('b的當前內存地址:',id(b))
    print('-----------------------------')
    c = a[0:3]  # c使用切片進行拷貝
    c.append(8)#在c的尾部添加數字8
    a.append(9)
    print('a:',a)
    print('b:',b)
    print('c:',c)
    print('a的內存地址:',id(a))
    print('b的內存地址:',id(b))
    print('c的內存地址:',id(c))#打印c的內存地址
    """
    a的初始內存地址: 2186126011016
    b的初始內存地址: 2186126011016
    a: [1, 2, 3, 4, 5, 6, 7]
    b: [1, 2, 3, 4, 5, 6, 7]
    a的當前內存地址: 2186126011016
    b的當前內存地址: 2186126011016
    -----------------------------
    a: [1, 2, 3, 4, 5, 6, 7, 9]
    b: [1, 2, 3, 4, 5, 6, 7, 9]
    c: [1, 2, 3, 8]
    a的內存地址: 2186126011016
    b的內存地址: 2186126011016
    c的內存地址: 2186126011976
    """
    
  • 顯然淺拷貝後變量的存放地址相同,僅僅是拷貝到內存地址,且其中一個變量發生增刪等操作會直接改變目標變量的值;

  • 深拷貝後變量的存放地址不同,說明另外開闢了新的內存空間存放拷貝後的變量,且其中一個變量的增刪操作不會不會對其餘的變量產生影響。

4. Numpy 中的深拷貝和淺拷貝

  • np.copy() 方法是 深拷貝
  • 切片操作是特殊的 淺拷貝;(注意與python的list切片使用是深拷貝,這是一種特殊的淺拷貝,因爲出現了新的內存地址,但是數據修改仍會同步)
  • 直接賦值給另一個變量是 淺拷貝
# 導入numpy
import numpy as np
a = np.arange(6)
print('一、淺拷貝')
#1、直接賦值法
b = a
#2、切片法
c = a[:]
print('a:',a)
print('b:',b)
print('c:',c)
print('改變b的第1個位置上的元素之後———')
# 改變a中第一個元素的值
a[0] = 4
c[2] = 7
print('a:',a,id(a))
print('b:',b,id(b))
print('c:',c,id(c))

print('二、深拷貝')
d = a.copy()
print('a:',a)
print('d:',d)
# 將a的第2個元素值也更改
a[1] = 5
print('賦值後:')
print('a:',a,id(a))
print('d:',d,id(d))
"""
一、淺拷貝
a: [0 1 2 3 4 5]
b: [0 1 2 3 4 5]
c: [0 1 2 3 4 5]
改變b的第1個位置上的元素之後———
a: [4 1 7 3 4 5] 2186126040480
b: [4 1 7 3 4 5] 2186126040480
c: [4 1 7 3 4 5] 2186126040960 #numpy中的切片的使用比較特殊,會發現存儲地址已經發出變化,但是a和c之間仍然會相互影響,所以這是一種特殊的淺拷貝。
二、深拷貝
a: [4 1 7 3 4 5]
d: [4 1 7 3 4 5]
賦值後:
a: [4 5 7 3 4 5] 2186126040480
d: [4 1 7 3 4 5] 2186125987392
"""
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章