python中的可变与不可变、深拷贝和浅拷贝

个人猜想(很遗憾失败了)

在硬盘或者系统中存在一个字符集

如果存在硬盘中,那么硬盘出厂的时候他的字符集所占用的空间就已经确定了。

如果存在于系统的话,硬盘应该在出厂的时候为系统设置一个存储系统字符集的地方。在安装系统的时候,把这个字符集放入约定的内存空间中。

当然,这个字符集不管是存在硬盘还是系统自带,硬盘中的这片内存区域是不允许改变的。所以不可变类型的原因就找到了。

文心一言告诉我,确实存在一个字符集,但并不存在于硬盘中,而是存在系统中,用于处理数据

不过可以确定的是,这些不可变数据的创建及存储是有一定规律的

测试一下

使用python输出不可变类型的内存地址

结论:
经过多次运行,这个内存地址在一个时间段内输出的内容是相同的
应该是某种机制在保护,程序结束后并不释放内存空间
而是等待一段时间的下次调用,用来节省资源的消耗

但是结果的差值都为32

a=1
b=2
print("a=",id(a))
print("b=",id(b))"""
a= 140731726750504
b= 140731726750536""""""
a= 140731562451752
b= 140731562451784
"""

使用 C语言输出不可变类型的内存地址

测试了一下C语言的,发他的内存地址是固定不会变化的

于是我想起来C语言编译型语言,于是又重新创建了一个代码相同的文件,结果竟然是相同的

#include <stdio.h>  int main() {  int a = 1;  int b = 2;  printf("变量a的内存地址是:%d\n", &a);  printf("变量b的内存地址是:%d\n", &b);  return 0;  
}//变量a的内存地址是:6422300
//变量b的内存地址是:6422296

尝试使用虚拟机的ubuntn系统下运行

python测试

结果显示差值为168,但是不会在一段时间内改变

a=1
b=2
print("a=",id(a))
print("b=",id(b))"""
a= 10894368
b= 10894400
"""

C语言测试

发现每一次的结果都不同,但是每次都相差4,由此想到了系统架构是64还是32,一时间大量的疑问涌入脑中,好吧,时间有限,停止思考,疑问封存

什么是可变与不可变

可变不可变,是指内存中的那块内容(value)是否可以被改变

  • 可变类型(mutable),创建后可以继续修改对象的内容(值)

    字典、列表

  • 不可变类型(unmutable) ,一旦创建就不可修改的对象(值)

    数字, 字符串,元组

什么是深拷贝和浅拷贝

 python中的copy 模块,可以实现拷贝功能

浅拷贝(就像快捷方式)

浅拷贝:引用(地址)拷贝,并没有产生新的空间。如果拷贝的是对象,原对象和copy对象都指向同一个内存空间,只拷贝父对象,不会拷贝对象的内部的子对象

  • 不会产生新的空间
  • 源对象和副本对象指向同一空间
  • 如果拷贝的是对象,子对象不会拷贝(不产生新的空间)

用法: copy.copy(变量) 会进行拷贝

深拷贝(真正的复制)

  • 会产生新的空间
  • 能够保持各自的独立性
  • 如果拷贝的是对象,子对象也会拷贝(产生新的空间)

深拷贝:会产生新的空间。如果拷贝的是对象,原对象和copy对象都指向不同的内存空间,会拷贝对象及其子对象(会产生新的空间)

用法:copy.deepcopy(变量名)

简单可变类型的拷贝

简单可变数据类型不管是深拷贝和浅拷贝,都会产生新的空间,而且保持各自的独立性

验证

浅拷贝

import copylist1 = [2, 4, 6]
# 浅拷贝
list2 = copy.copy(list1)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
list1.append(8)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
# 测试结果
""""
list1= [2, 4, 6] 2366561172928
list2= [2, 4, 6] 2366558942976
list1= [2, 4, 6, 8] 2366561172928
list2= [2, 4, 6] 2366558942976
"""

深拷贝

import copylist1=[2,4,6]
# 深拷贝
list2=copy.deepcopy(list1)print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
list1.append(8)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
# 测试结果
"""
list1= [2, 4, 6] 2447599320576
list2= [2, 4, 6] 2447598755904
list1= [2, 4, 6, 8] 2447599320576
list2= [2, 4, 6] 2447598755904
"""

复杂可变类型的拷贝

复杂类型的内存地址是引用

list1 = [1, 3, 5]
list2 = [2, 4, 6]list3 = [list1, list2]print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
print("list3=", list3, id(list3))
print("list3[0]=", list3[0], id(list3[0]))"""
嵌套只是引用
list1= [1, 3, 5] 2090564943424
list2= [2, 4, 6] 2090564397632
list3= [[1, 3, 5], [2, 4, 6]] 2090562664192
list3[0]= [1, 3, 5] 2090564943424
"""

浅拷贝(对快捷方式创建快捷方式)

  • 复杂可变类型的 浅拷贝,实际上是引用拷贝,无法保持独立性

验证

import copylist1 = [1, 3, 5]
list2 = [2, 4, 6]list3 = [list1, list2]# 已知,复杂类型的内存地址是引用
# 所以对复杂类型进行浅拷贝
list4 = copy.copy(list3)list1.append(7)
print("list1=", list1, id(list1))
print("list3=", list3, id(list3))
print("list4=", list4, id(list4))
print("list4=[0]", list4[0], id(list4[0]))"""运行结果:在浅拷贝结束后
对简单类型进行数据的添加
复杂类型的内容会改变,浅拷贝的内容也会发生改变
而浅拷贝的地址改变了
所以浅拷贝针对复杂类型最顶层
list1= [1, 3, 5, 7] 3144178450048
list3= [[1, 3, 5, 7], [2, 4, 6]] 3144178363904
list4= [[1, 3, 5, 7], [2, 4, 6]] 3144178364544
list4=[0] [1, 3, 5, 7] 3144178450048
"""

深拷贝(真正的复制)

  • 复杂可变类型的 深拷贝,此时会产生新的内存空间

验证

import copylist1 = [1, 3, 5]
list2 = [2, 4, 6]list3 = [list1, list2]# 进行深拷贝
list4 = copy.deepcopy(list3)list1.append(7)
print("list1=", list1, id(list1))
print("list3=", list3, id(list3))
print("list4=", list4, id(list4))
print("list4=[0]", list4[0], id(list4[0]))"""运行结果:
深拷贝将复杂类型中的简单类型数据也进行了复制
实现了完全复制
list1= [1, 3, 5, 7] 1623394860736
list3= [[1, 3, 5, 7], [2, 4, 6]] 1623394774528
list4= [[1, 3, 5], [2, 4, 6]] 1623394775104
list4=[0] [1, 3, 5] 1623394775360
"""

简单不可变类型的拷贝(都是浅拷贝)

验证

import copydef copy_popy():tuple1=(1,3,5)# 浅拷贝tuple2=copy.copy(tuple1)print("tuple1=",tuple1,id(tuple1))print("tuple2=",tuple2,id(tuple2))"""运行结果:tuple1= (1, 3, 5) 2239384263296tuple2= (1, 3, 5) 2239384263296"""tuple1=(1,3,5)
#深拷贝
tuple2=copy.deepcopy(tuple1)print("tuple1=",tuple1,id(tuple1))
print("tuple2=",tuple2,id(tuple2))"""运行结果
tuple1= (1, 3, 5) 2406599105152
tuple2= (1, 3, 5) 2406599105152
"""

复杂不可变类型的拷贝

复杂不可变类型的本质

import copylist1=[1,3,5]
list2=[2,4,6]tuple1=(list1,list2)print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))"""运行结果
list1= [1, 3, 5] 2175399394816
tuple1= ([1, 3, 5], [2, 4, 6]) 2175399258432
tuple1[0]= [1, 3, 5] 2175399394816
"""

验证

浅拷贝

只关心最外层的数据类型是什么,如果是不可变类型,直接引用,没有办法保证数据的独立性

外层为不可变,内层为可变

import copylist1=[1,3,5]
list2=[2,4,6]tuple1=(list1,list2)# 进行浅拷贝
tuple2=copy.copy(tuple1)print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))"""运行结果
list1= [1, 3, 5] 2384705011392
tuple1= ([1, 3, 5], [2, 4, 6]) 2384704858432
tuple1[0]= [1, 3, 5] 2384705011392tuple2= ([1, 3, 5], [2, 4, 6]) 2384704858432
tuple2[0]= [1, 3, 5] 2384705011392
"""
外层为可变,内层为不可变
import copylist1=(1,3,5)
list2=(2,4,6)tuple1=[list1,list2]# 进行浅拷贝
tuple2=copy.copy(tuple1)print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))"""运行结果
list1= (1, 3, 5) 2192295467648
tuple1= [(1, 3, 5), (2, 4, 6)] 2192295837376
tuple1[0]= (1, 3, 5) 2192295467648tuple2= [(1, 3, 5), (2, 4, 6)] 2192295274688
tuple2[0]= (1, 3, 5) 2192295467648
"""

深拷贝

这个数据是否有可变的数据类型,如果有它就会为可变类型开辟多个空间存储数据和地址,达到保证数据独立性的作用

外层为可变类型
import copylist1=(1,3,5)
list2=(2,4,6)tuple1=[list1,list2]# 进行深拷贝
tuple2=copy.deepcopy(tuple1)print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))"""运行结果
list1= (1, 3, 5) 2050110790272
tuple1= [(1, 3, 5), (2, 4, 6)] 2050111160000
tuple1[0]= (1, 3, 5) 2050110790272tuple2= [(1, 3, 5), (2, 4, 6)] 2050111074560
tuple2[0]= (1, 3, 5) 2050110790272
"""
外层为不可变类型 
import copylist1 = [1, 3, 5]
list2 = [2, 4, 6]tuple1 = (list1, list2)# 进行深拷贝
tuple2 = copy.deepcopy(tuple1)print("list1=", list1, id(list1))
print("tuple1=", tuple1, id(tuple1))
print("tuple1[0]=", tuple1[0], id(tuple1[0]))
print("tuple2=", tuple2, id(tuple2))
print("tuple2[0]=", tuple2[0], id(tuple2[0]))"""运行结果
list1= [1, 3, 5] 2221492256448
tuple1= ([1, 3, 5], [2, 4, 6]) 2221492103488
tuple1[0]= [1, 3, 5] 2221492256448tuple2= ([1, 3, 5], [2, 4, 6]) 2221492102912
tuple2[0]= [1, 3, 5] 2221492170816
"""
内外都不可变
import copylist1 = (1, 3, 5)
list2 = (2, 4, 6)tuple1 = (list1, list2)# 进行深拷贝
tuple2 = copy.deepcopy(tuple1)print("list1=", list1, id(list1))
print("tuple1=", tuple1, id(tuple1))
print("tuple1[0]=", tuple1[0], id(tuple1[0]))
print("tuple2=", tuple2, id(tuple2))
print("tuple2[0]=", tuple2[0], id(tuple2[0]))"""运行结果
list1= (1, 3, 5) 2647937981056
tuple1= ((1, 3, 5), (2, 4, 6)) 2647938197824
tuple1[0]= (1, 3, 5) 2647937981056tuple2= ((1, 3, 5), (2, 4, 6)) 2647938197824
tuple2[0]= (1, 3, 5) 2647937981056
"""

注意:只要是可变类型不管是深拷贝都会开辟新的空间 

切片拷贝(变量名[:])

切片拷贝,是一种浅拷贝,副本对象和原对象指向同一个空间

简单可变类型

list1 = [1, 3, 5]list2 = list1[:]print("list1=", list1, id(list1))
print("list2=", list2, id(list2))list2.append(7)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))"""运行结果
list1= [1, 3, 5] 1612210008768
list2= [1, 3, 5] 1612211181632list1= [1, 3, 5] 1612210008768
list2= [1, 3, 5, 7] 1612211181632
"""

复杂不可变类型

list1 = [1, 3, 5]
list2 = [2, 4, 6]tuple1=(list1,list2)tuple2=tuple1[:]print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple2=",tuple2,id(tuple2))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))
list1.append(7)
print("tuple2[0]=",tuple2[0],id(tuple2[0]))"""运行结果得出,切片拷贝是浅拷贝
list1= [1, 3, 5] 2281363043008
tuple1= ([1, 3, 5], [2, 4, 6]) 2281364482816
tuple2= ([1, 3, 5], [2, 4, 6]) 2281364482816tuple1[0]= [1, 3, 5] 2281363043008
tuple2[0]= [1, 3, 5] 2281363043008
tuple2[0]= [1, 3, 5, 7] 2281363043008
"""

字典拷贝 (字典名.copy())

字典提供一个copy()方法,也是浅拷贝,虽然地址发生改变,但是内部的对象仍然是链接状态

test_dict1={"age":[10,20,30]}test_dict2=test_dict1.copy()print("test_dict1=",test_dict1,id(test_dict1))
print("test_dict2=",test_dict2,id(test_dict2))
test_dict1["age"][0]=100print("test_dict1=",test_dict1,id(test_dict1))
print("test_dict2=",test_dict2,id(test_dict2))"""运行结果显示,字典拷贝为浅拷贝
test_dict1= {'age': [10, 20, 30]} 2561919905472
test_dict2= {'age': [10, 20, 30]} 2561921341312test_dict1= {'age': [100, 20, 30]} 2561919905472
test_dict2= {'age': [100, 20, 30]} 2561921341312
"""

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/447635.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SimpleDateFormat 格式化 Date 时间戳

前言 Date 是 Java 中经常用来表示时间的类型&#xff0c;但将 Date 类型的数据发送给前端时&#xff0c;通常会呈现出乱码的状态&#xff0c;用户不宜理解&#xff0c;所以要通过 SimpleDateFormat 把 Date 类型的数据格式化为用户容易理解的格式 如下是 Date 的格式&#xff…

【2024美赛E题】985博士解题思路分析(持续更新中)!

【2024美赛E题】985博士解题思路分析&#xff01; 加群可以享受定制等更多服务&#xff0c;或者搜索B站&#xff1a;数模洛凌寺 联络组织企鹅&#xff1a;936670395 以下是E题老师的解题思路&#xff08;企鹅内还会随时更新文档&#xff09;&#xff1a; 2024美赛E题思路详解…

北朝隋唐文物展亮相广西,文物预防性保护网关保驾护航

一、霸府名都——太原博物馆收藏北朝隋朝文物展 2月1日&#xff0c;广西民族博物馆与太原博物馆携手&#xff0c;盛大开启“霸府名都——太原博物馆北朝隋文物展”。此次新春展览精选了北朝隋唐时期150多件晋阳文物珍品。依据“巍巍雄镇”“惊世古冢”“锦绣名都”三个单元&am…

车载语音交互赛道研究:大模型揭幕2.0时代 商业模式重塑

大模型正给车载语音交互赛道带来颠覆性变革。 根据高工智能汽车研究院调研获取的信息&#xff0c;核心原因为&#xff1a;1.0时代&#xff0c;车载语音交互玩家可使用自身的小模型&#xff1b;2.0时代&#xff0c;很可能需基于通用大模型&#xff08;训练成本极为高昂&#xf…

【2024年美国大学生数学建模竞赛】F题非法的野生动物贸易 完整数据

小云更新了全网最全的F题数据 另外也为大家分享&#xff1a; 技术文档&#xff0c;包括问题分析、建立模型、求解结果等&#xff0c;配套有思路分析视频、代码讲解视频。美赛官方限制总页数为25页&#xff0c;我们的思路长度为35页以上。所有模型都有求解代码和指标&#xff0…

ManageEngine推出云原生身份平台以解决劳动力IAM挑战

ManageEngine推出云原生身份平台以解决企业员工身份与访问管理&#xff08;IAM&#xff09;面临的挑战。该公司还为其本地身份治理和管理&#xff08;IGA&#xff09;解决方案添加了先进的安全功能。 IAM 内置通用目录可在企业应用程序之间集中管理用户身份&#xff0c;使用身…

嵌入式系统设计师之存储管理

目录 一、Flat存储管理方式&#xff08;I&#xff09; 二、分区存储管理&#xff08;II&#xff09; 1、固定分区 2、可变分区 3、内存保护 三、地址重定位 (II) 1、逻辑地址 2、物理地址 四、页式存储管理 &#xff08;II&#xff09; 五、虚拟存储管理&#xff08;II&#x…

【c语言】简单贪吃蛇的实现

目录 一、游戏说明 ​编辑 二、地图坐标​ ​编辑 三、头文件 四、蛇身和食物​ 五、数据结构设计​ 蛇节点结构如下&#xff1a; 封装一个Snake的结构来维护整条贪吃蛇&#xff1a;​ 蛇的方向&#xff0c;可以一一列举&#xff0c;使用枚举&#xff1a; 游戏状态&a…

22.java-网络编程

网络编程 服务器介绍 ​ 服务器就是一台配置很高的电脑 互联网架构分类 BS架构 &#xff1a; Browser / Server ​ 优点&#xff1a;不需要下载客户端&#xff0c;使用起来非常方便。 ​ 缺点&#xff1a;用户体验比较差 CS架构 &#xff1a; Client / Server ​ 缺点…

数据结构——链表的一点小收获(内存指向)

1.整数变量赋值 a 2 b a b 3 结果&#xff1a; a 2 b 3 当给b重新赋值时&#xff0c;内存指向发生变换 2.链表之间的赋值与列表、字典相似&#xff0c;是内存指向的赋值 a [1] b a b[0] 2&#xff08;这里其实是修改变量值&#xff0c;如果改为b [2]则会改变…

spring-authorization-server 公共客户端方式获取授权码和Token的流程

spring-authorization-serve【版本1.2.1】官方文档中提及了关于RegisteredClient中所涉及的客户端身份验证方法&#xff0c;也就是RegisteredClient中提及的clientAuthenticationMethods属性对应的“none”值&#xff0c;目前clientAuthenticationMethods属性支持的值包含&…

springboot149智慧图书管理系统设计与实现

智慧图书管理系统的设计与实现 摘 要 如今社会上各行各业&#xff0c;都在用属于自己专用的软件来进行工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。互联网的发展&#xff0c;离不开一些新的技术&#xff0c;而新技术的产生往往是为了解决现…