【Python】通过现象和本质理解python赋值、浅拷贝、深拷贝

原文作者 :我辈李想
版权声明 :文章原创,转载时请务必加上原文超链接、作者信息和本声明。


文章目录


前言

我理解中,深拷贝和浅拷贝是Python数据类型可变和不可变的延伸,主要是处理组合数据类型:元组、列表、集合、字典。我们这里主要以元组和列表为例记性展示。

  1. 对于1级不可变数据类型,浅拷贝和深拷贝id地址不同,拷贝数据一致不改变。
  2. 对于1级可变数据类型,浅拷贝和深拷贝id地址不同,拷贝数据一致不改变。

一、看问题本质

1.认识赋值、浅拷贝、深拷贝

示例代码

python 复制代码
import copy

a = [1, 2]
b = [3, 4]
c = (a, b)
d = [a, b]

print('---1层不可变,2层可变---')
赋值_c = c
浅拷贝_c = copy.copy(c)
深拷贝_c = copy.deepcopy(c)
print('a',id(a))
print('b',id(b))
print('c',id(c))
print('赋值_c',id(赋值_c))
print('浅拷贝_c',id(浅拷贝_c))
print('深拷贝_c',id(深拷贝_c))

print('---1层可变,2层可变---')
赋值_d = d
浅拷贝_d= copy.copy(d)
深拷贝_d = copy.deepcopy(d)
print('a',id(a))
print('b',id(b))
print('d',id(d))
print('赋值_d',id(赋值_d))
print('浅拷贝_d',id(浅拷贝_d))
print('深拷贝_d',id(深拷贝_d))

示例结果

通过示例结果,可以看到对于不可变数据类型,赋值和浅拷贝是一样的,指向的id没有发生变化。深拷贝id发生变化;对于可变数据类型,赋值时id未发生变化,浅拷贝和深拷贝的id均发生变化。

二.看问题现象

通过改变可变类型,我们查看赋值、浅拷贝、深拷贝的具体变化。上一步中我们使用了1级数据和2级数据,这里我们就通过改变他们来试验。

1.改变1级数据,这里要改变d

示例代码

python 复制代码
import copy


a = [1, 2]
b = [3, 4]
c = (a, b)
d = [a, b]

# 1层不可变,2层可变
print('---1层不可变,2层可变---')
赋值_c = c
浅拷贝_c = copy.copy(c)
深拷贝_c = copy.deepcopy(c)
print('a',id(a))
print('b',id(b))
print('c',id(c))
print('赋值_c',id(赋值_c))
print('浅拷贝_c',id(浅拷贝_c))
print('深拷贝_c',id(深拷贝_c))

print('---1层可变,2层可变---')
赋值_d = d
浅拷贝_d= copy.copy(d)
深拷贝_d = copy.deepcopy(d)
print('a',id(a))
print('b',id(b))
print('d',id(d))
print('赋值_d',id(赋值_d))
print('浅拷贝_d',id(浅拷贝_d))
print('深拷贝_d',id(深拷贝_d))

d.append(10)
print('****改变1级数据,d中增加元素')
print('---1层不可变,2层可变---')
print('a',a)
print('b',b)
print('c',c)
print('赋值_c',赋值_c)
print('浅拷贝_c',浅拷贝_c)
print('深拷贝_c',深拷贝_c)
print('---1层可变,2层可变---')
print('a',a)
print('b',b)
print('d',d)
print('赋值_d',赋值_d)
print('浅拷贝_d',浅拷贝_d)
print('深拷贝_d',深拷贝_d)

示例结果

这个示例中不需要看c,我们直接看d的相关数据,通过示例结果可以看出,对于1级可变数据,浅拷贝和深拷贝id不同但是结果一样,对于1级可变数据类型,浅拷贝和深拷贝id地址不同,拷贝数据一致不改变

2.改变2级数据,这里改变a或者b

示例代码

python 复制代码
import copy


a = [1, 2]
b = [3, 4]
c = (a, b)
d = [a, b]

# 1层不可变,2层可变
print('---1层不可变,2层可变---')
赋值_c = c
浅拷贝_c = copy.copy(c)
深拷贝_c = copy.deepcopy(c)
print('a',id(a))
print('b',id(b))
print('c',id(c))
print('赋值_c',id(赋值_c))
print('浅拷贝_c',id(浅拷贝_c))
print('深拷贝_c',id(深拷贝_c))

print('---1层可变,2层可变---')
赋值_d = d
浅拷贝_d= copy.copy(d)
深拷贝_d = copy.deepcopy(d)
print('a',id(a))
print('b',id(b))
print('d',id(d))
print('赋值_d',id(赋值_d))
print('浅拷贝_d',id(浅拷贝_d))
print('深拷贝_d',id(深拷贝_d))


a.append(10)
print('****改变2级数据,a中增加元素')
print('---1层不可变,2层可变---')
print('a',a)
print('b',b)
print('c',c)
print('赋值_c',赋值_c)
print('浅拷贝_c',浅拷贝_c)
print('深拷贝_c',深拷贝_c)
print('---1层可变,2层可变---')
print('a',a)
print('b',b)
print('d',d)
print('赋值_d',赋值_d)
print('浅拷贝_d',浅拷贝_d)
print('深拷贝_d',深拷贝_d)

示例结果

通过示例结果可以看出,对于一层不可变二层可变的数据,赋值和浅拷贝id地址相同数据一致均改变,深拷贝与其他两项id不同、数据不一致未改变;对于一层可变二层可变的数据,赋值、浅拷贝、深拷贝id地址均不同,赋值和浅拷贝数据一致均改变,深拷贝数据未改变。

相关推荐
上位机付工8 分钟前
C#与倍福TwinCAT3进行ADS通信
开发语言·c#
励志不掉头发的内向程序员17 分钟前
STL库——二叉搜索树
开发语言·c++·学习
至此流年莫相忘31 分钟前
设计模式:模板方法模式
java·开发语言·设计模式
土了个豆子的1 小时前
02.继承MonoBehaviour的单例模式基类
开发语言·visualstudio·单例模式·c#·里氏替换原则
qq_172805591 小时前
Go 自建库的使用教程与测试
开发语言·后端·golang
久绊A1 小时前
Hydra-SSH 破解安全防范
开发语言·php
ZZHow10241 小时前
02OpenCV基本操作
python·opencv·计算机视觉
阿昭L1 小时前
c++中获取随机数
开发语言·c++
计算机学长felix2 小时前
基于Django的“酒店推荐系统”设计与开发(源码+数据库+文档+PPT)
数据库·python·mysql·django·vue
3壹2 小时前
数据结构精讲:栈与队列实战指南
c语言·开发语言·数据结构·c++·算法