【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地址均不同,赋值和浅拷贝数据一致均改变,深拷贝数据未改变。

相关推荐
C++业余爱好者几秒前
Java 提供了8种基本数据类型及封装类型介绍
java·开发语言·python
林杜雨都3 分钟前
Action和Func
开发语言·c#
皮卡龙5 分钟前
Java常用的JSON
java·开发语言·spring boot·json
火山灿火山33 分钟前
Qt常用控件(三)
开发语言·qt
利刃大大1 小时前
【JavaSE】十三、枚举类Enum && Lambda表达式 && 列表排序常见写法
java·开发语言·枚举·lambda·排序
float_六七1 小时前
Java反射:万能遥控器拆解编程
java·开发语言
AI Echoes1 小时前
构建一个LangChain RAG应用
数据库·python·langchain·prompt·agent
han_hanker1 小时前
java 异常类——详解
java·开发语言
源码获取_wx:Fegn08951 小时前
基于springboot + vue健身房管理系统
java·开发语言·前端·vue.js·spring boot·后端·spring
LinHenrY12271 小时前
初识C语言(自定义结构:结构体)
c语言·开发语言