python 引用,浅拷贝,深拷贝

引用

当对象是不可变类型的时候,int、float、double、string、tuple(纯tuple),遇到“引用”问题时,虽然起初两个变量指向同一个内存地址,但是改变了其中一个值,并不会影响另外一个(会重新开辟内存地址)。

当对象是可变类型的时候,list、dic,遇到“引用”问题,会一直共享一块内存地址,改变了其中一个,另外一个也就改变了。

#1 不可变量,更改后内存地址发生改变
a = 1
b = a
a = a+1
print('values {} id {}'.format(a,id(a)))
print('values {} id {}'.format(b,id(b)))

output:
values 2 id 1545235968
values 1 id 1545235936

# 2 可变类型,更改后内存地址不变
l1 = [1,2,[3,4],5]
l2 = l1
print(id(l1))
print(id(l2))
l1.append(6)
print(l2)

#output:
911276241736
911276241736
[1, 2, [3, 4], 5, 6]

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

三种浅拷贝的方法:

import copy

l1 = [1,2,[3,4],5]
#1 利用[:]
l2 = l1[:]
print('1: {} \t {}'.format(id(l1),id(l2)))

#2 利用copy.copy()
l2 = copy.copy(l1)
print('2: {} \t {}'.format(id(l1),id(l2)))

#3 利用list.copy()
l2 = l1.copy()
print('3: {} \t {}'.format(id(l1),id(l2)))

output:
1: 911276084616          911247796040
2: 911276084616          911276277704
3: 911276084616          911247796040

它会有一个问题,就是更改list中的list结构,会使整体改变。 

l1 = [1,2,[3,4],5]
l2 = l1[:]
#1  浅层更改
l1.append(6)
print('1: {} \t {}'.format(l1,l2))

output:
1: [1, 2, [3, 4], 5, 6]          [1, 2, [3, 4], 5]


#2 深层更改
l1[2].append(6)
print('2: {} \t {}'.format(l1,l2))

output:
2: [1, 2, [3, 4, 6], 5]          [1, 2, [3, 4, 6], 5]

我的理解就是:

不可变的就是不可变,可变的里面如果是可变的那就是可变,可变的里面不可变那就是不可变。

在#1中,l1.append(6) 不会改变,因为6是和1,2,5同等级的,int型不可变。
       但是在#2中,l1[2].append(6),浅拷贝会变,因为它的等级不是int而是list,list可变。

深拷贝:是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。

import copy

l1 = ['a',['b','c'],'d']

l2 = copy.deepcopy(l)
l1[1].append('m')
print(l1)
print(l2)

output:
['a', ['b', 'c'], 'd']
['a', ['b', 'c', 'm'], 'd']

所以涉及到列表的嵌套结构的时候,还是用deepcopy()比较好,以防万一。

参考:

https://blog.csdn.net/i_love_zxy/article/details/102713917

发布了56 篇原创文章 · 获赞 29 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/foneone/article/details/103395084