Python-引用&浅拷贝&深拷贝

浅拷贝: 指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用


深拷贝: 指的是重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中

对于可变对象深浅拷贝:

=浅拷贝:值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相等

 

对于不可变对象的深浅拷贝:

不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。

#codding: utf-8

"""
常量值: 在整个程序的完整生命周期中只会创建一次的变量被称为常量
    1、str、int、 float、bool 这四个类型的值都是常量值,下面的例子中不论怎么操作都不会创建一个新的值
"""

import copy

a = "cpython"         #创建常量
b = a                 #引用
c = copy.copy(a)      #浅拷贝
d = copy.deepcopy(a)  #深拷贝

"""
执行结果:
id(a)
Out[12]: 140347862604464
id(b)
Out[13]: 140347862604464
id(c)
Out[14]: 140347862604464
id(d)
Out[15]: 140347862604464
"""

a = 10                   #创建常量
b = a                    #引用
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[20]: 140348122786384
id(b)
Out[21]: 140348122786384
id(c)
Out[22]: 140348122786384
id(d)
Out[23]: 140348122786384

a = 2.4                    #创建常量
b = a                      #引用
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[28]: 140347862758640
id(b)
Out[29]: 140347862758640
id(c)
Out[30]: 140347862758640
id(d)
Out[31]: 140347862758640

a = True                    #创建常量
b = a                       #引用
c = copy.copy(a)
d = copy.deepcopy(a)

id(a)
Out[36]: 4502985424
id(b)
Out[37]: 4502985424
id(c)
Out[38]: 4502985424
id(d)
Out[39]: 4502985424

'''
#对象值:除了常量值以外,其他一切都是对象(类),例如:class, list, dict, tuple, set, queue, deque....
#对象的特征是,每次实例化一个对象都会创建new一个新内存,因此每次实例化一个对象,它们的id都是独立的
'''
a = []
b = []

id(a)
Out[42]: 140348133547520
id(b)
Out[43]: 140347588520896

class TEST:
    def __init__(self):
        self.world = "world"
        
a = TEST()
b = TEST()
id(a)
Out[51]: 140348133753232
id(b)
Out[52]: 140347862738592

#引用: python采取完全引用策略,所以像做下面这种操作,并不是复制/拷贝,而是引用

a = []                      #实例化一个列表对象,变量a的指针指向该列表对象
b = a                       #变量b的指针指向a所指向的列表对象
id(a)
Out[55]: 140348133760384
id(b)
Out[56]: 140348133760384

### 拷贝
a = [1,2,3,4]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[61]: 140348135105280
id(b)
Out[62]: 140348135105280
id(c)
Out[63]: 140348135105664     #c分配了一块新的内存
id(d)
Out[64]: 140348133627136     #d分配了一块新的内存 
id(a[0])
Out[65]: 140348122786096      
id(b[0])
Out[66]: 140348122786096      #成员值是常量,拷贝的是引用
id(c[0])
Out[67]: 140348122786096      #成员值是常量,拷贝的是引用
id(d[0])
Out[68]: 140348122786096      #成员值是常量,拷贝的是引用

##浅拷贝
a = [1,2,3,[4,5,6]]
b = a
c = copy.copy(a)
id(a[3])
Out[75]: 140348133697664
id(b[3])
Out[76]: 140348133697664
id(c[3])
Out[77]: 140348133697664

Out[77]: 140348133697664
a[3][0]= 10                            #a[3]发生变化
Out[77]: 140348133697664
b                                      #b[3]引用a[3],所以b[3]也发生变化
Out[79]: [1, 2, 3, [10, 5, 6]]
c
Out[80]: [1, 2, 3, [10, 5, 6]]

b[3][1] = 20                           #b[3]的子对象发生变化
b
Out[82]: [1, 2, 3, [10, 20, 6]]
a                                      #a[3]的子对象也会发生变化
Out[83]: [1, 2, 3, [10, 20, 6]]
c
Out[84]: [1, 2, 3, [10, 20, 6]]

#深拷贝
a = [1,2,3,[4,5,6]]
b = copy.deepcopy(a)
id(a)
Out[87]: 140348133734144              #分配一块新的内存
id(b)
Out[88]: 140348133698496              #分配一块新的内存

a[3][0]=10                           
a
Out[90]: [1, 2, 3, [10, 5, 6]]        #a对象中的子对象发生变化
b                                    
Out[91]: [1, 2, 3, [4, 5, 6]]         #b对象中的子对象仍不变

'''
###结论:
1、不论是浅拷贝还是深拷贝,都不拷贝最终的常量值,而是引用
2、浅拷贝引用的是一维的成员
3、深拷贝递归的是创建对象,只有遇到常量值是会引用
'''

 

posted @ 2021-12-06 16:40  美女爱找茬  阅读(70)  评论(0编辑  收藏  举报