python 引用、copy 与deepcopy

一、引用

a=[1,2,3]

b=a

此为列表引用,a和b的内存地址是一样的,都是指向列表[1,2,3]。其实是一个列表,两个名字。操作其中一个变量改变列表,另外一个变量显示的列表也同时改变。

a=[1,2,3]
b=a
print(id(a))
print(id(b))
输出:
2132799892168
2132799892168
a.append(4)
print(b)
输出:
[
1, 2, 3, 4]
def lis(li):
    li.append(4)

a=[1,2,3]
lis(a)
print('a=',a)

输出:
a= [1, 2, 3, 4]

可以看到,即使函数没有返回值,列表a的内容也是被改变了。
这是因为不管变量名有多少个,列表其实只有一个。通过任意一个变量名对列表进行操作,列表改变,不管通过哪一个变量名引用列表的内容自然也发生改变。
引用与C语言的指针非常相像。

举个例子:一个人有两个名字张三、李四。如果张三中了500万,那么李四肯定中了500万。李四有1000万财产,张三肯定也有1000万财产。

此处,这个人就相当于列表。张三、李四这两个名字相当于变量名,指向这个人。这个人还可以叫王五、赵六。只要一个名字对应的这个人发生了改变,引用其余的名字时,这个人必然发生了同样的改变。

由于引用是对一个列表进行操作,列表会随着操作进行改变,无法保存原列表。

二、deepcopy

import copy
a
=[1,2,[1,3]] b=copy.deepcopy(a) print(id(a)) print(id(b))
print(id(a[2]))
print(id(b[2]))
输出: 
2599508758664
2599508759880
2239363432264
2239363470600



a、b的内存地址已经完全不一样,a、b指向的列表完全相互独立,是两个完全不同的列表,相互之间不再存在影响。

三、copy

copy是介于引用和deepcopy之间的一种模式。

对于最外层的列表,相当于deepcopy,相互独立。

但是对于嵌套的列表,他相当于引用

a=[1,2,[1,3]]
b=a.copy()
print(id(a))
print(id(b))
print(id(a[2]))
print(id(b[2]))

输出结果:
3166059548808
3166059550024
3166059511624
3166059511624

可以看到,对于a、b这两个变量,他们的内存地址是不一样的,相互独立
但是对于嵌套列表a[2]、b[2]来说,内存地址是一样的,是对同一个列表的引用。

 同样,对于一个列表a添加一个列表b作为元素,则该元素也会随着列表b的变化而变化

a=[1,2,3]
b=[4,5,6]
a.append(b)
b[0]=0
print(a)

输出:
[1, 2, 3, [0, 5, 6]]  #可以看到,当b改变后,a[3]也随之改变

若想相互独立,由于b中元素不含有列表,此处可以用copy:
a=[1,2,3]
b=[4,5,6]
a.append(b.copy())
b[0]=0
print(a)

输出:
[1, 2, 3, [4, 5, 6]]

如果b中同样嵌套列表,则需要用deepcopy

 

posted @ 2017-12-24 09:33  roadcode  阅读(299)  评论(0编辑  收藏  举报