欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python基础之六:深浅拷贝问题

程序员文章站 2022-06-08 14:14:41
...

Python基础之六:深浅拷贝问题

一、对象赋值

1、代码

l1 = [1, '晴朗', [2, '小明']]
l2 = l1
print(l1 is l2)#True
l1[2][0] = 3
print(l2)#[1, '晴朗', [3, '小明']]
l1.append(4)
print(l2)#[1, '晴朗', [3, '小明'], 4]

2、图解

Python基础之六:深浅拷贝问题

3、分析

1、创建了一个名为l1的变量,这个变量指向一个list对象
2、把l1的值赋值给l2,那么l2变量将指向l1变量对应的对象(内存地址),可以理解为,对象的赋值都是进行对象引用(内存地址)传递,也就是说"l1 is l2l",“l1[i] is l2[i]”
3、由于l1和l2指向同一个对象,所以对l1的任何修改都会体现在l2上

二、浅拷贝

1、代码

l1 = [1, '晴朗', [2, '小明']]
l2 = l1.copy()
print(l1 is l2)#False
l1[2][0] = 3
print(l2)#[1, '晴朗', [3, '小明']]
l1.append(4)
print(l2)#[1, '晴朗', [3, '小明']]
print(l1[2][0] is l2[2][0])#True

2、图解

Python基础之六:深浅拷贝问题

3、分析

1、创建了一个名为l1的变量,这个变量指向一个list对象
2、通过copy模块里面的浅拷贝函数copy(),对l1指向的对象进行浅拷贝,然后浅拷贝生成的新对象赋值给l2变量
2.1、浅拷贝会创建一个新的对象,这个例子中"l1 is not l2"
2.2、但是,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址),也就是说"l1[i] is l2[i]"
3、由于l1和l2不指向同一个对象,但在拷贝时生成的对象与原来被拷贝对象中的元素分别指向同一个内存地址,所以对l1的元素任何修改都会体现在l2上,但对l1的单独操作不会引起l2变化(如添加元素)

三、深拷贝

1、代码

import copy #导入copy模块
l1 = [1, '晴朗', [2, '小明']]
l2 = copy.deepcopy(l1)
print(l1 is l2)#False
l1[2][0] = 3
print(l2)#[1, '晴朗', [2, '小明']]
l1.append(4)
print(l2)#[1, '晴朗', [2, '小明']]
print(l1[0] is l2[0])#True
print(l1[2] is l2[2])#False

2、图解

Python基础之六:深浅拷贝问题

3、分析

1、创建了一个名为l1的变量,这个变量指向一个list对象
2、通过copy模块里面的浅拷贝函数deepcopy(),对l1指向的对象进行深拷贝,然后深拷贝生成的新对象赋值给l2变量
2.1、深拷贝会创建一个新的对象,这个例子中"l1 is not l2"
2.2、但是,对于对象中的元素,深拷贝都会重新生成一份,而不是简单的使用原始元素的引用(内存地址)
3、由于l1和l2不指向同一个对象,且l1和l2对象中的元素也不指向同一个内存地址,所以对l1的任何修改都不会体现在l2上

四、总结

1、Python中对象的赋值都是进行对象引用(内存地址)
2、传递/使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用
3、如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
4、对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有被拷贝一说
5、如果元祖变量只包含原子类型对象,则不能深拷贝(没有意义,结果都一样),看下面的例子:

import copy #导入copy模块
t1 = (1, '晴朗', 2, '小明')
t2 = copy.copy(t1)
print(t1 is t2)#True
import copy #导入copy模块
t1 = (1, '晴朗', 2, '小明')
t2 = copy.deepcopy(t1)
print(t1 is t2)#True
相关标签: Python基础 python