python变量的引用赋值及深浅拷贝

1. python的变量

  python中的所有变量,实际存储的 都是真实数据在内存上的地址。这也很好解释了“python一切皆对象“,一切皆通过调用的方式达成目的。所有的变量其实都是内存地址的引用。

python变量 -> 内存地址
在这里插入图片描述
这里的id函数即为查看该对象在内存上的引用地址。
在这里插入图片描述
  根据引用方式的不同,python变量的类型可划分为两类:可变数据类型不可变数据类型

  • 可变数据类型:list,dict,set
  • 不可变数据类型:int,float,str,tuple

1.1 可变数据类型

  可变数据类型在通过 = 赋值时,实质是传递的引用,也就是“=”右边数据的内存地址
python中可变数据类型的引用1
  以上的例子中,a是一个list,即可变数据类型,当执行b = a,b和a共用同一个内存地址,如果在a上进行了修改的操作,a的内存地址不会发生改变;所对应的,因为这里的b所映射的数据,实质就是a所对应的数据,b会和a的数据保持一致。但是如果是对a进行重新赋值,即使是完全相同的元素,内存地址也会发生变化,如下图。
python中可变数据类型的引用2

1.2 不可变数据类型

  而不可变数据在通过 = 传值时,实质也是传递的同一个内存地址,但若对该数据进行修改或重赋值,则会在内存的不同位置上新建对象。并且相同的值在内存中的位置是相同的
python中不可变数据类型的引用
  上例中的c为int,即不可变数据类型,执行d = c后,传递的同样为相同的内存地址,但是若对c进行了修改或重赋值,c所对应的内存地址也会随之变化。
并且在不可变数据中,完全相同的值永远只会映射到同一个内存地址。

2. 深浅拷贝

首先需要再说明一个新的对应关系。

2.1 内存地址以及实际存储数据之间的关系

内存地址以及实际存储数据之间的关系

从底层一点的角度去描述的话,两者的关系实质是在程序执行时:

  • cpu中地址总线上所对应的某个地址以及cpu所调用的在数据存储器(一般为RAM)中的数据的关系。

简单来讲,就是一种映射关系,就像是

  • python变量内存地址之间的关系。

所以在python的数据引用或赋值的数据传递过程,其实是经历了3层的结构:

python变量 -> 内存地址 -> 数据存储器中对应的数据

2.2 若拷贝对象是可变数据类型

  若拷贝对象是可变数据类型,或包含可变数据类型,那么可变数据类型的这部分数据

  • 浅拷贝只会创建新的内存地址,而2个不同地址所指向的数据,是同一批数据;也就是2份不同的地址,同1份数据
  • 深拷贝除了会新建内存地址,该新建的内存地址所指向的数据存储器中的数据,同样也是新建的;也就是2份不同地址,2份相同的数据
    可变数据类型的深浅拷贝
      如果通过上述还没理解到深浅拷贝,再举个例子:这里python变量和内存地址的关系,以及内存地址和所指向数据的关系,可以想象成是电脑中程序的快捷方式 及 程序的主执行程序 的关系。
      例如主程序其实是放在D盘某个目录中的,但是通过点击C盘桌面上的快捷方式,由于快捷方式和主程序之间存在映射链接关系,所以程序依然成功执行。
      那么对可变数据类型的浅拷贝,相当于就是又新建了一个快捷方式,即新建了内存地址,实际都是指向同一个路径中的主程序。
      而深拷贝,相当于是把主程序的整个目录在E盘复制粘贴了一份,且新建了一个快捷方式,并指向E盘中的主程序的路径。

2.3 若拷贝对象是不可变数据类型

  若拷贝对象是不可变数据类型,那就很简单了,浅拷贝和深拷贝的效果是一样的,可以回顾 1.2 不可变数据类型“相同的值在内存中的位置是相同的” 这句话。
在这里插入图片描述
  按照 2.2 的梳理,浅拷贝是2份不同内存地址,同1份数据,那么因为相同的值在内存中的位置是相同的,即相同的不可变数据,在内存上只会有一份,所以内存地址也只有一份。因此这里只会产生1份内存地址,同1份数据;同理,深拷贝也只会产生1份内存地址,同1份数据。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值