首先,我们知道在 Python3 中,有 6 个标准的数据类型,他们又分为可变和不可变
不可变数据类型(3个)
-
Number(数字)
-
String(字符串)
-
Tuple(元组)
可变数据类型(3个)
-
List(列表)
-
Dictionary(字典)
-
Set(集合)
在 Python 中,其实是没有那种传统意义上的变量,我们通常说的变量其实是一个标签,或者是一个指针变量,因为它保存的是变量的一个地址
对于不可变类型,赋值、浅拷贝、深拷贝其实都是创建一个标签,指向了变量的地址,它的 id 都是一样的。而当我们改变其中一个标签的值的时候,其实就是将这个标签重新指向一个新的地址,旧的变量的引用计数会减一,随之它的 id 也会变化
In [1]: from copy import copy,deepcopy
In [2]: a = 'a,b,c,d'
In [3]: b = a
In [4]: c = copy(a)
In [5]: d = deepcopy(a)
In [6]: a,d
Out[6]: ('a,d','a,d')
In [7]: id(a),id(b),id(c),id(d)
Out[7]: (4592638320,4592638320,4592638320)
In [8]: a = '1,2,3,4'
In [9]: a,d
Out[9]: ('1,4',d')
In [10]: id(a),id(d)
Out[10]: (4592787504,4592638320)
对于可变类型,赋值是创建一个标签,和不可变类型一致
浅拷贝的时候,标签会重新开辟一个新的地址,不占用被拷贝对象的引用计数。新的标签也是指向变量(或者叫数组)的地址,它们 id 是不同的
深拷贝的时候,标签会重新开辟一个新的地址,并将被拷贝的对象放入新的地址。此时,内存地址中就会有两份一模一样的数据,但是地址不同, 当然,它们 id 也是不同的
In [1]: from copy import copy,deepcopy
In [2]: a = [1,[2,3],'4']
In [3]: b = a
In [4]: c = copy(a)
In [5]: d = deepcopy(a)
In [6]: a,d
Out[6]: ([1,'4'],[1,'4'])
In [7]: id(a),id(d)
Out[7]: (4394796232,4394796232,4397213000,4397312072)
In [8]: a[1][0] = 0
In [9]: a,d
Out[9]: ([1,[0,'4'])
In [10]: id(a),id(d)
Out[10]: (4394796232,4397312072)
有一点需要注意的是,当我们重新给不可变类型的标签赋值时,它会释放标签的引用计数,并且改变它的地址。但是下列第 11 行代码,我将它的标签重新赋值后,它的地址还是没变(13行),这是为什么呢?
In [11]: a[0] = 0
In [12]: a,d
Out[12]: ([0,'4'])
In [13]: id(a),id(d)
Out[13]: (4394796232,4397312072)
这是因为刚刚我们查看的是整个数组的 id ,而不是某一个元素的 id
重新给数组中的某一个元素赋值,当我们单独查看它的 id 时,它的 id 已经发生了变化(14,17行)
In [14]: id(a[0])
Out[14]: 4365118432
In [15]: a[0] = 5
In [16]: id(a),id(d)
Out[16]: (4394796232,4397312072)
In [17]: id(a[0])
Out[17]: 4365118592
对于 Python 的浅拷贝和深拷贝其实是针对于那些可变类型的,因为对不可变类型没有意义,赋值操作就足够了 (编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|