Python中的深浅拷贝

文章目录

  • [一. 数据类型](#一. 数据类型)
    • [1. 不可变数据类型](#1. 不可变数据类型)
    • [2. 可变数据类型](#2. 可变数据类型)
    • [3. 赋值](#3. 赋值)
  • [二. 深浅拷贝](#二. 深浅拷贝)
    • [1. 浅拷贝](#1. 浅拷贝)
      • [① ==简单的==可变数据类型](#① ==简单的==可变数据类型)
      • [② ==复杂的==可变数据类型](#② ==复杂的==可变数据类型)
      • [③ ==简单的==不可变数据类型](#③ ==简单的==不可变数据类型)
      • [④ ==复杂的==不可变数据类型](#④ ==复杂的==不可变数据类型)
      • [⑤ 浅拷贝栗子](#⑤ 浅拷贝栗子)
        • [Ⅰ. 切片操作](#Ⅰ. 切片操作)
        • [Ⅱ. 工厂函数](#Ⅱ. 工厂函数)
        • [Ⅲ. copy模块中的copy函数](#Ⅲ. copy模块中的copy函数)
    • [2. 深拷贝](#2. 深拷贝)
      • [① ==简单的==可变数据类型](#① ==简单的==可变数据类型)
      • [② ==复杂的==可变数据类型](#② ==复杂的==可变数据类型)
      • [③ ==简单的==不可变数据类型](#③ ==简单的==不可变数据类型)
      • [④ ==复杂的==不可变数据类型](#④ ==复杂的==不可变数据类型)
    • [3. 深浅拷贝特殊案例](#3. 深浅拷贝特殊案例)
      • [① 可变嵌套不可变类型](#① 可变嵌套不可变类型)
      • [② ==不可变嵌套可变类型==](#② ==不可变嵌套可变类型==)
    • [4. 总结](#4. 总结)
      • [① 浅拷贝只能拷贝一层](#① 浅拷贝只能拷贝一层)
      • [② 深拷贝能拷贝多层](#② 深拷贝能拷贝多层)
      • [③ 可变类型拷贝可开辟新的内存空间](#③ 可变类型拷贝可开辟新的内存空间)
      • [④ 不可变类型拷贝对象的引用关系,不可开辟新的内存空间](#④ 不可变类型拷贝对象的引用关系,不可开辟新的内存空间)
      • [⑤ 特殊:不可变嵌套可变,深拷贝时,整体都可以进行完全拷贝](#⑤ 特殊:不可变嵌套可变,深拷贝时,整体都可以进行完全拷贝)

一. 数据类型

  • 变量:是一个系统表的元素,拥有指向对象的连接空间
  • 对象:被分配的一块内存,存储其所代表的值
  • 引用:是自动形成的从变量到对象的指针
  • 类型:属于对象,而非变量

1. 不可变数据类型

一旦创建就不可修改的对象,包括数值类型、字符串、布尔类型、元组

python 复制代码
#定义一个变量a
a = "python"

print(id(a))
python 复制代码
b=10
print(id(b))#140710918126944

b="hello"
print(id(b))#1629196172080

2. 可变数据类型

可以修改的对象,包括列表、字典、集合

3. 赋值

只是复制了新对象的引用,不会开辟新的内存空间

python 复制代码
a = 10
b = a
print(id(a))#140711658356064
print(id(b))#140711658356064

c = [1, 2, 3]
d = c
print(id(c))#1930836595208
print(id(d))#1930836595208

二. 深浅拷贝

拷贝就是复制操作,其拷贝的值是相同的,但引用关系有所不同

1. 浅拷贝

浅拷贝,能力有限,只能拷贝最外层对象(只需要为外层开辟内存空间),无法拷贝内层对象

① 简单的可变数据类型

对于简单的可变数据类型,浅拷贝相当于把原对象的值进行拷贝,需要在内存中开辟一块新的内存空间

python 复制代码
import copy

list1 = [1, 3, 5]
list2 = copy.copy(list1)

# 值-相同
print(list1)  # [1, 3, 5]
print(list2)  # [1, 3, 5]

# 地址-不同
print(id(list1))  # 1541605108232
print(id(list2))  # 1541605108296

② 复杂的可变数据类型

对于复杂的可变数据类型,浅拷贝只能拷贝可变数据类型的最外层对象,而无法拷贝内层对象,所以只需要为最外层对象开辟内存空间,内层对象拷贝后的引用关系与原对象保持不变

python 复制代码
import copy

list1 = [1, 3, 5,[7,9]]
list2 = copy.copy(list1)

# 值-相同
print(list1)  # [1, 3, 5,[7,9]]
print(list2)  # [1, 3, 5,[7,9]]

# 地址-不同
print(id(list1))  # 1541605108232
print(id(list2))  # 1541605108296

# 地址-相同
print(id(list1[3]))  # 2850758572616
print(id(list2[3]))  # 2850758572616

③ 简单的不可变数据类型

对于简单的不可变数据类型,不可变数据类型地址一旦固定,值就无法改变了,又由于浅拷贝需要把自身的对象空间赋值给另外一个变量,为了保证数据一致,只能让其指向相同的内存空间(不需要额外开辟内存空间)

python 复制代码
import copy

a = (1, 3, 5)
b = copy.copy(a)

# 值-相同
print(a)  # (1, 3, 5)
print(b)  # (1, 3, 5)

# 地址-相同
print(id(a))  # 2350406710360
print(id(b))  # 2350406710360

④ 复杂的不可变数据类型

对于复杂的不可变数据类型,浅拷贝只能拷贝变量的值,无法拷贝内存空间(无法开辟新的内存空间),无法拷贝内层对象

python 复制代码
import copy

a = (1, 3, 5, (7, 9))
b = copy.copy(a)

# 值-相同
print(a)  # (1, 3, 5, (7, 9))
print(b)  # (1, 3, 5, (7, 9))

# 地址-相同
print(id(a))  # 2350406710360
print(id(b))  # 2350406710360

# 地址-相同
print(id(a[3]))  # 2109112683592
print(id(b[3]))  # 2109112683592

无法拷贝内层对象

python 复制代码
import copy

a = (1, 3, 5, (7, 9))
b = copy.copy(a)

# 值-相同
print(a)  # (1, 3, 5, [7, 9]))
print(b)  # (1, 3, 5, [7, 9])

# 地址-相同
print(id(a))  # 2350406710360
print(id(b))  # 2350406710360

# 地址-相同
print(id(a[3]))  # 2109112683592
print(id(b[3]))  # 2109112683592

⑤ 浅拷贝栗子

Ⅰ. 切片操作
python 复制代码
lst = [1,2,[3,4]]
切片操作:lst1 = lst[:] 或者 lst1 = [each for each in lst]

[:]它与[0:]相似,意思是从0索引拆分到末尾。它返回一个新列表。

Ⅱ. 工厂函数
python 复制代码
lst1 = list(lst)
Ⅲ. copy模块中的copy函数
python 复制代码
lst1 = copy.copy(lst)

但是在lst中有一个嵌套的list[3,4],如果我们修改了它,情况就不一样了。

2. 深拷贝

深拷贝:和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。

① 简单的可变数据类型

对于简单的可变数据类型,深拷贝可以对对象进行完全拷贝,生成一块独立的内存空间,两个变量没有任何关系

python 复制代码
import copy

a = [1, 3, 5]
b = copy.deepcopy(a)

# 值-相同
print(a)  # [1, 3, 5]
print(b)  # [1, 3, 5]

# 地址-不相同
print(id(a))  # 1763734399496
print(id(b))  # 1763734399560

② 复杂的可变数据类型

对于复杂的可变数据类型,深拷贝可以对对象进行完全拷贝,不仅可以拷贝外层对象,也可以拷贝内层对象,而且完全独立

python 复制代码
import copy

a = [1, 3, 5, [7, 9]]
b = copy.deepcopy(a)

# 值-相同
print(a)  # [1, 3, 5, [7, 9]]
print(b)  # [1, 3, 5, [7, 9]]

# 地址-不相同
print(id(a))  # 2891527236360
print(id(b))  # 2891527236616

# # 地址-不相同
print(id(a[3]))  # 2891527236296
print(id(b[3]))  # 2891527283912

③ 简单的不可变数据类型

对于简单的不可变数据类型,深拷贝也只能拷贝对象的引用关系,所以看到的记过就是a和b只想了相同的内存空间

python 复制代码
import copy

a = (1, 3, 5)
b = copy.deepcopy(a)

# 值-相同
print(a)  # (1, 3, 5)
print(b)  # (1, 3, 5)

# 地址-相同
print(id(a))  # 1719625069656
print(id(b))  # 1719625069656

④ 复杂的不可变数据类型

对于复杂的不可变数据类型,深拷贝也只能拷贝对象的引用关系,所以看到的记过就是a和b只想了相同的内存空间

python 复制代码
import copy

a = (1, 3, 5, (7, 9))
b = copy.deepcopy(a)

# 值-相同
print(a)  # (1, 3, 5, (7, 9))
print(b)  # (1, 3, 5, (7, 9))

# 地址-相同
print(id(a))  # 1928373693320
print(id(b))  # 1928373693320

# 地址-相同
print(id(a[3]))  # 1928373701640
print(id(b[3]))  # 1928373701640

3. 深浅拷贝特殊案例

① 可变嵌套不可变类型

外层是可变类型,多以可以进行完全拷贝(需生成内存空间),但内层对象是不可变数据类型,所以只能拷贝引用关系

python 复制代码
import copy

a = [1, 3, 5, (7, 9)]
b = copy.copy(a)
c = copy.deepcopy(a)

# 值-相同
print(a)  # [1, 3, 5, (7, 9)]
print(b)  # [1, 3, 5, (7, 9)]
print(c)  # [1, 3, 5, (7, 9)]

# 地址-不同
print(id(a))  # 2197686397896
print(id(b))  # 2197686397960
print(id(c))  # 2197686398216

# 地址-相同
print(id(a[3]))  # 2197686094920
print(id(b[3]))  # 2197686094920
print(id(c[3]))  # 2197686094920

② 不可变嵌套可变类型

浅拷贝结论与之前结论一致,都只能拷贝引用关系

深拷贝,有点不同,如果这种类型使用深拷贝,其整体都可以进行完全拷贝

python 复制代码
import copy

a = (1, 3, 5, [7, 9])
b = copy.copy(a)
c = copy.deepcopy(a)

# 值-相同
print(a)#(1, 3, 5, [7, 9])
print(b)#(1, 3, 5, [7, 9])
print(c)#(1, 3, 5, [7, 9])

#地址ab同,与c不同
print(id(a))#2983608461896
print(id(b))#2983608461896
print(id(c))#

#地址ab同,与c不同
print(id(a[3]))#2983608498888
print(id(b[3]))#2983608498888
print(id(c[3]))#2983608499144

浅拷贝

深拷贝

4. 总结

① 浅拷贝只能拷贝一层

② 深拷贝能拷贝多层

③ 可变类型拷贝可开辟新的内存空间

④ 不可变类型拷贝对象的引用关系,不可开辟新的内存空间

⑤ 特殊:不可变嵌套可变,深拷贝时,整体都可以进行完全拷贝

相关推荐
用户277844910499310 小时前
借助DeepSeek智能生成测试用例:从提示词到Excel表格的全流程实践
人工智能·python
JavaEdge在掘金12 小时前
ssl.SSLCertVerificationError报错解决方案
python
我不会编程55513 小时前
Python Cookbook-5.1 对字典排序
开发语言·数据结构·python
李少兄13 小时前
Unirest:优雅的Java HTTP客户端库
java·开发语言·http
老歌老听老掉牙13 小时前
平面旋转与交线投影夹角计算
python·线性代数·平面·sympy
满怀101513 小时前
Python入门(7):模块
python
无名之逆13 小时前
Rust 开发提效神器:lombok-macros 宏库
服务器·开发语言·前端·数据库·后端·python·rust
你觉得20513 小时前
哈尔滨工业大学DeepSeek公开课:探索大模型原理、技术与应用从GPT到DeepSeek|附视频与讲义下载方法
大数据·人工智能·python·gpt·学习·机器学习·aigc
似水এ᭄往昔13 小时前
【C语言】文件操作
c语言·开发语言
啊喜拔牙13 小时前
1. hadoop 集群的常用命令
java·大数据·开发语言·python·scala