#

5. 深浅copy

1. 引子

如果把一个列表的值引用给另一个列表,它们的值和id是否相等?

l1 = ['xxq',18,'male'] 		#定义列表l1
l2 = l1		#把l1的值引用给l2

print(l1)	#输出l1的内容
print(l2)	#输出l2的内容
print(id(l1))	#输出l1的id
print(id(l2))	#输出l2的id

['xxq', 18, 'male']
['xxq', 18, 'male']
58970184
58970184

这里可以看出,他们输出的内容完全相等。


l1 = ['xxq',18,'male']
l2 = l1     # 这不叫copy
l1[0] = 'qwe'	#将l1的第一个值改变

print(l1)
print(l2)
print(id(l1))
print(id(l2))

['qwe', 18, 'male']
['qwe', 18, 'male']
17354824
17354824

这里可以看出:二者分隔不开,l1改l2也跟着改,因为指向的就是同一个地址。

但是,如果想要把2个列表完全独立开,互不影响,该怎么操作呢?

2. 需求:

  • 拷贝一下原列表产生一个新的列表

  • 想让两个列表完全独立开,并且针对的是改操作的独立而不是读操作

3. 浅Copy

浅Copy:是把原列表第一层的内存地址不加区分完全copy一份给新列表

小白鼠实验:

list1=[
   'egon',
   'lxx',
   [1,2]
]

list3=list1.copy()
print (list3)
print (id(list1))
print (id(list3))      #列表的内存地址不一样

print(id(list1[0]),id(list1[1]),id(list1[2]))
print(id(list3[0]),id(list3[1]),id(list3[2]))  # 列表里的值的内存地址一样



由此可以看出:l3拷贝了l1的值,但是l3和l1的id是不同的。


实验1:对于不可变类型的赋值,都是产生了新值,让原列表的索引指向新的内存地址,并不会影响新列表。

list1=[
   'egon',
   'lxx',
   [1,2]
]

list1[0]='EGON'
list1[1]='LXX'
list1[2]=123


实验2:但对于可变类型,我们可以改变可变类型中包含的值,但内存地址不变即原列表的索引指向仍然指向原来的内存地址,于是新列表也跟着一起受影响,如下:

//并没有完全独立开

list1[2][0]=111
list1[2][1]=222
print(list1)
print(list3)

综合上述实验1和实验2可以得出,要想copy得到的新列表与原列表的改操作完全独立开,必须有一种可以区分开可变类型与不可变类型的copy机制,这就是深copy

4. 深Copy

  • 区分开可变类型与不可变类型,实现完全独立开

  • 针对不可变类型,用原来的地址,针对可变类型,创建一个新的容器(list,dic),但里面的内容都指向原来的内存地址

# 要使用深Copy,要先导入库:
import copy

然后使用

import copy
list1=[
    'egon',
    'lxx',
    [1,2]
]

list3=copy.deepcopy(list1)

print(id(list1))
print(id(list3))
print(list3)

         不可变        不可变        可变
print(id(list1[0]),id(list1[1]),id(list1[2]))
print(id(list3[0]),id(list3[1]),id(list3[2]))
'''
4497919088 4498367856 4498449216
4497919088 4498367856 4498595328  #不可变类型的内存地址一样,可变类型的内存地址不一样
'''
print(list3)
print(id(list1[2][0]),id(list1[2][1]))
print(id(list3[2][0]),id(list3[2][1]))

list1[0]='EGON'
list1[1]='LXX'

list1[2][0]=111
list1[2][1]=222
print(list1)

print(list3)

posted @ 2020-06-02 15:41  苒苒物华休&  阅读(228)  评论(0编辑  收藏  举报