前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python的赋值、浅层拷贝和深层拷贝解释

python的赋值、浅层拷贝和深层拷贝解释

原创
作者头像
mariolu
修改2024-01-16 10:56:11
14500
代码可运行
修改2024-01-16 10:56:11
举报
运行总次数:0
代码可运行

或许你在其他编程语言比如C++有听说过拷贝分深拷贝和浅拷贝。这两个概念区别就是你复制的是一份对象的引用还是对象本身。今天我们来看一下python的赋值、浅层拷贝和深层拷贝的区别。

一、赋值和拷贝

开始之前,先看一段代码。

代码语言:python
代码运行次数:0
复制
import copy
arr = [ [1, 2, 3], [4, 5, 6] ]

assigned = arr  #assign
swallow_copied = copy.copy(arr)  #swallow copy
deep_copied = copy.deepcopy(arr)  # deep copy

这里看到了我们声明了一个二维数组arr,并使用这个arr赋值了assigned、浅拷贝了swallow_copied和深拷贝了deep_copied。

1.1 对象的内存布局

我们使用python tour来看下三者在object层是如何布置的。

很清楚看到 :

  • arr的object对象的引用 赋值给了assigned,也就是assigned的object是等价于arr
  • swallow_copied复制了第一层的对象[[][]], 但是就最终的object[1,2,3]和[4,5,6]和arr并无区别
  • deep_copied则是在object层完整地拷贝了一份新的object。和arr是完全两码事。

1.2 修改object

接上段代码,接着来修改object。加入了在swallow_copied和deep_copied的操作代码,并和原来的arr进行比较。

代码语言:python
代码运行次数:0
复制
import copy
arr = [ [1, 2, 3], [4, 5, 6] ]

assigned = arr  #assign
swallow_copied = copy.copy(arr)  #swallow copy
deep_copied = copy.deepcopy(arr)  # deep copy


print("before:")
print("arr:", arr)
print("swallow_copied:", swallow_copied)
print("deep_copied:", deep_copied)

swallow_copied.append([7, 8, 9])
swallow_copied[0].append(3.5)

print()
print("after swallow copy:")
print("arr:", arr)
print("swallow_copied:", swallow_copied)

deep_copied.append([7, 8, 9])
deep_copied[0].append(3.5)

print()
print("after deep copy:")
print("arr:", arr)
print("deep_copied:", deep_copied)

使用python tour观察这段代码,你看到区别了吗?

一开始我们的数组长这样:

before:

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

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

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

经过这两行代码进行浅层拷贝之后

代码语言:javascript
复制
swallow_copied.append([7, 8, 9])
swallow_copied[0].append(3.5)

swallow_copied变成

after swallow copy:

arr: [ [1, 2, 3, 3.5], [4,5,6] ]

swallow_copied: [ [1, 2, 3, 3.5], [4, 5, 6], [7, 8, 9]]

可以看到虽然我只是操作swallow_copied,但是由于swallow_copied和arr共享了swallow_copied[0]的对象,所以这里arr[0]也跟着改变。

然后再经过这两行代码进行深层拷贝之后

代码语言:python
代码运行次数:0
复制
deep_copied.append([7, 8, 9])
deep_copied[0].append(3.5)

deep_copied变成

after deep copy:

arr: [ [1, 2, 3, 3.5], [4,5,6] ]

deep_copied: [ [1, 2, 3, 3.5], [4, 5, 6], [7, 8, 9]]

可以看到操作deep_copied并没有改变arr。

二、mutable和immutable

我们来看下python的赋值copy和deepcopy操作,以及对mutable和immutable类型操作的区别。

先来看一段代码

代码语言:python
代码运行次数:0
复制
x = 5
print(x)

y=x
print(y)

x += 1
print(x)
print(y)

从这段代码的执行结果来看,x+=1并没有改变y。也就是说虽然y=x,但是x和y并不是同一个object。

2.1 mutable和非mutable类型

python把object分为两种类型:

  • 一种叫immutable,包括integer,float和string。
  • 另一种叫mutable,包括list,dict等容器。

python对不同类型也有不同的处理方式

  • 这里y=x,也就是说每次处理immutable类型,都会真真实实地创建新的object
  • 而处理mutable类型,object还是那个object,只是object里面的values被改变了。你操作了这个object的reference。

2.2 浅拷贝和深拷贝的区别

浅层拷贝和深拷贝只有在操作immutable对象时有区别。

  • mutable对象如果持有的是immutable的对象,比如说[1,2,3]这里mutable的[]持有的是immutable的1,2,3。浅层拷贝和深拷贝[1,2,3]是没有区别的
  • 如果mutable对象持有的mutable对象。比如说[[1,2,3], [4,5,6]]这里mutable的[[], []] 持有的是mutable的[]。那么mutable的浅层拷贝创建了第一层级的对象,里面的内嵌对象只是保留了reference。但是深拷贝除了会创建第一层级的对象之外,里面的内嵌对象也会创建新的对象。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、赋值和拷贝
    • 1.1 对象的内存布局
      • 1.2 修改object
      • 二、mutable和immutable
        • 2.1 mutable和非mutable类型
          • 2.2 浅拷贝和深拷贝的区别
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
          http://www.vxiaotou.com