1. 程式人生 > >Python賦值、淺拷貝、深拷貝的區別

Python賦值、淺拷貝、深拷貝的區別

ID IV 元素 改變 拷貝 但是 int 需要 copy

一、賦值
  • str例子
>>> a = 'hello'
>>> b = 'hello'
>>> c = a
>>> [id(x) for x in (a,b,c)]
[42654216, 42654216, 42654216]

a,b,c三者地址一樣,相當於a=b=c。賦值系統先給變量或對象(這裏的hello)分配了內存,然後將地址賦給a,b,c。所以他們的地址是相同的。

>>> a = 'world'
>>> [id(x) for x in
(a,b,c)] [42654384, 42654216, 42654216] >>> print(a,b,c) world hello hello

這時只有a的地址和值變了,但是b,c地址和值都沒有變。因為str的不可變性,a要重新賦值則需重新開辟內存空間,所以a的值改變,a指向的地址改變。b, c由於‘hello‘的不變性,不會發生改變。

  • list例
>>> a = ['hello']
>>> b = ['hello']
>>> c = a
>>> [id(x) for
x in (a,b,c)] [42670920, 42671816, 42670920]

但是這種情況卻不一樣了,a和b的地址不同。為何?
因為str是不可變的,所以同樣是‘hello‘只有一個地址,但是list是可變的,所以必須分配兩個地址。

>>> a[0] = 'world'
>>> [id(x) for x in (a,b,c)]
[42670920, 42671816, 42670920]
>>> print(a,b,c)
['world'] ['hello'] ['world']

這時a,c的值和地址均改變,但二者仍相同,b不改變。由於list的可變性,所以修改list的值不需要另外開辟空間,只需修改原地址的值。所以a,c均改變。

二、淺拷貝與深拷貝
  • 程序
import copy
a = [1,2,3,4,['a','b']] #原始對象
b = a #賦值
c = copy.copy(a) #淺拷貝
d = copy.deepcopy(a) #深拷貝
a.append(5)
a[4].append('c')
print('a = ',a)
print('b = ',b)
print('c = ',c)
print('d = ',d)
  • 結果
a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c =  [1, 2, 3, 4, ['a', 'b', 'c']]
d =  [1, 2, 3, 4, ['a', 'b']]
  1. copy.copy 淺拷貝 只拷貝父對象,不會拷貝對象的內部的子對象。
  2. copy.deepcopy 深拷貝 拷貝對象及其子對象

總結:

  1. 賦值是將一個對象的地址賦值給一個變量,讓變量指向該地址( 舊瓶裝舊酒 )。

  2. 淺拷貝是在另一塊地址中創建一個新的變量或容器,但是容器內的元素的地址均是源對象的元素的地址的拷貝。也就是說新的容器中指向了舊的元素( 新瓶裝舊酒 )。

  3. 深拷貝是在另一塊地址中創建一個新的變量或容器,同時容器內的元素的地址也是新開辟的,僅僅是值相同而已,是完全的副本。也就是說( 新瓶裝新酒 )。

Python賦值、淺拷貝、深拷貝的區別