Python 引用、浅拷贝、深拷贝解析

时间:2022-03-09 19:50:38

引用

Python是动态数据类型的语言,故在对变量进行赋值时是不用制定变量类型的。
或者说,你可以把变量赋值的过程,当作是贴一个标签,去引用该数据。

看下面的例子:

 In [54]: a=4

 In [55]: b=a

 In [56]: id(a)
 Out[56]: 1652425264

 In [57]: id(b)
 Out[57]: 1652425264

可以看到,a与b志向了同一个地址。这便是引用


浅拷贝与深拷贝

先来看一个例子:

In [58]: import copy

In [59]: a=[1,2,3]

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

In [61]: c=copy.deepcopy(a)

上面便是调用了标准模块copy,b浅拷贝了a,c深拷贝了a。
接下来,再看看3个变量的地址:

In [62]: id(a)
Out[62]: 2069478787912

In [63]: id(b)
Out[63]: 2069479182856

In [64]: id(c)
Out[64]: 2069479074568

可以看到,相对与引用,浅拷贝与深拷贝后,变量指向的地址都变了。那么,深拷贝与
浅拷贝之间到底有什么区别呢?咱们接下去分析结果:

In [65]: id(a[0])
Out[65]: 1652425168

In [66]: id(b[0])
Out[66]: 1652425168

In [67]: id(c[0])
Out[67]: 1652425168

这下明白了吧!对于一个列表里的元素,深拷贝和浅拷贝还是指向了原来的内存地址。
看到这里是不是会误以为它们两个没区别呢?好吧,再看看下面:

In [92]: a={'people':['brad','Alex'],'I':'xiaole'}

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

In [94]: c=copy.deepcopy(a)

In [95]: id(a['people'])
Out[95]: 2069478460104

In [96]: id(b['people'])
Out[96]: 2069478460104

In [97]: id(c['people'])
Out[97]: 2069479089608

可以看到,对于‘people’,浅拷贝还是指向了原来的内存地址。而深拷贝,
就是实实在在指向不同的地址,说白了就是把数据放在了不同的地方。
再说白了,浅拷贝就是在在内存中只额外创建第一层数据。

好吧,至此以为全都弄明白了,那请解释下下面的结果:

In [98]: id(a['I'])
Out[98]: 2069482265320

In [99]: id(b['I'])
Out[99]: 2069482265320

In [100]: id(c['I'])
Out[100]: 2069482265320

为何对于元素‘I’,又指向了同一个地址。说好的元素指向不同了呢?
想弄明白,看下面的重点提醒,并去琢磨下吧。

重点提醒!!!

对于数字和字符串,赋值、浅拷贝和深拷贝的值都指向同一个内存地址。

In [68]: a=3

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

In [70]: c=copy.deepcopy(a)

In [71]: id(a)
Out[71]: 1652425232

In [72]: id(b)
Out[72]: 1652425232

In [73]: id(c)
Out[73]: 1652425232

In [74]: a='brad'

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

In [76]: c=copy.deepcopy(a)

In [77]: id(a)
Out[77]: 2069482263528

In [78]: id(b)
Out[78]: 2069482263528

In [79]: id(c)
Out[79]: 2069482263528

说明:本人所用的解释器为Ipython