版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
python的可变与不可变数据类型一切皆对象在Python中,一切类型都可以被视为对象(object),包括:变量、常量、函数、列表等等。在下面的代码中,测试是否为对象时都返回True#一切皆对象x=10defmy_func():return"qklabs"y=[1,2,3]print("xisobject:{}".format(isinstance(x,object)))print("10isobject:{}".format(isinstance(10,object)))print("my_funcisobject:{}".format(isinstance(my_func,object)))print("yisobject:{}".format(isinstance(y,object)))print("boolisobject:{}".format(isinstance(True,object)))print("stringisobject:{}".format(isinstance("qklabs",object)))不可变对象(Immutableobjects)Python中分为不可变(Immutable)和可变(Mutable)对象。不可变对象是指对象的实例一旦创建就不可改变,这表现为该对象在内存中的地址不变,同时该地址中的内容也保持不变。如下面的代码,无论声明多少个变量,只要它的值相同,这些对象的内存地址就会不变。a=5b=5c=b#int类型是不可变类型,下面输出的变量的内存地址是一样的。#说明不可变类型只要值相同,不管创建多少个变量,它们的都指向相同的内存地址print("aaddress:{}".format(hex(id(a))))print("baddress:{}".format(hex(id(b))))print("caddress:{}".format(hex(id(c))))这与c++语言是不同的,在c++中,每个变量或常量都有独立的内存空间,地址都不相同,不管它们的值是相等还是不相等,通过指针,可以修改内存地址中的内容。在Python中,不可变对象是不允许修改对应的内存地址的内容的。但这不代表不允许修改变量的值,如:a+=10#当a+10后,a创建了一个新的对象,该对象指向了新的地址print("afteradd,aaddress:{}".format(hex(id(a))))当变量a增加一个值之后,它指向了一个新的地址。这与c++也是不同的,在c++中,仍然保持原有的a内存地址不变。可变对象(Mutableobjects)顾名思义,可变对象就是可以修改对象对应的内存中的内容,而该对象的地址在内容修改之后仍然保持不变。并且每个对象都有独立的内存地址,如列表类型:list_1=[1,2]list_2=[1,2]#每个对象都有独立的内存地址print("list_1address:{}".format(hex(id(list_1))))print("list_2address:{}".format(hex(id(list_2))))#修改list_1中的变量,在此打印对象的地址,发现它与修改之前一致。list_1[0]=3print("list_1address:{}".format(hex(id(list_1))))不可变对象与可变对象的组合在Python中如果不可变对象与可变对象组合在一起形成的对象,是可变还是不可变呢,看下面的代码:#下面演示可变和不可变的组合的情况,这里的list是可变类型,tuple是不可变类型tuple1=([1,2],"qklabs")print("tuple1address:{}".format(hex(id(tuple1))))#修改其中的list内容tuple1=([2,2],"qklabs")#tuple是不可变类型,list是可变类型,因此修改了list,导致对象的地址也发生变化,说明组合后的类型是不可变类型。print("afterchanged:tuple1address:{}".format(hex(id(tuple1))))说明组合后的对象是不可变对象。为什么需要不可变对象不可变类型是通过Python内存管理机制来实现的,这是因为Python对不可变类型进行了缓存,无论声明多少个值相同的变量,实际上都指向同个内存地址。这种机制减少了内存消耗和提升程序运行速度,通过直接从缓存获取运算结果比重新进行计算要快得多。实现自定义类的不可变性质默认情况下,Python自定义类的对象是可变对象,如下例子:classSymbol:def__init__(self,name):=namesb1=Symbol("1")sb2=Symbol("1")print("Symbol1isSymbol1:{}".format(sb1==sb2))#对象sb1和sb2的地址并不相同,print("Symbol1address:{}Symbol2address:{}".format(hex(id(sb1)),hex(id(sb2))))即使该对象的成员变量的值一样,它们仍然不相等。所以上述的sb1==sb2返回False。在一些场合中,我们需要使用不可变对象,使得Symbol("1")==Symbol("1")成立。例如在符号运算中,比较两个符号是否相等,如:Symbol("x")==Symbol("x")这是最快速的方式。当然也可以通过运算符重载而无需将该类变成不可变类型的类。但是Python中,不可变类型的好处还不止这些。下面的代码将Symbol类变成不可变类型,这里定义了一个新的类SymbolCache:fromfunctoolsimportlru_cacheclassSymbolCache:@lru_cache(maxsize=None)def__new__(cls,*args,**kwargs):returnobject.__new__(cls)def__init__(self,name):=namesbc1=SymbolCache("1")sbc2=SymbolCache("1")print("SymbolCache1isSymbolCache1:{}".format(sbc1==sbc2))#对象sbc1和sbc2的地址相同print("SymbolCache1address:{}SymbolCache2address:{}".format(hex(id(sbc1)),hex(id(sbc2))))上述的测试结果是sbc1==sbc2是成立的,同时它们的对象地址也相同。这里利用Python的缓存(Cache)机制将数据存储在内存中,以便下次能够更快地访问这些数据,这也是一个典型的用空间换时间的例子。一般用于缓存的内存空间是固定的,当有更多的数据需要缓存的时候,需要将已缓存的部分数据清除后再将新的缓存数据放进去。需要清除哪些数据,就涉及到了缓存置换的策略,LRU(LeastRecentlyUsed,最近最少使用)是很常见的一个,也是Python中提供的缓存置换策略。在类的构造过程中,通过装饰器lru_cache将该类返回的对象缓存,也就是说将类的对象设置成不可变对象。这里的maxsize=None,表示不限制缓存大小。不可变对象在运算中的加速在运算中,不可变对象如果已经缓存,可以直接从缓存中获取,而无需重复计算,看下面的例子:defadd(n1,n2):print(f"计算n1+n2......")returnn1+n2r1=add(1,2)print("n1+n2={}".format(r1))r2=add(1,2)r3=add(3,4)+r2print("n1+n2={}".format(r3))上述代码定义了一个简单的add函数实现两个数相加。我们调用了该函数三次,打印了三次"计算n1+n2....”信息,说明函数确实执行了三次。但是这里的r2计算和r1计算是一样的,有没有可能在执行r2计算时不重复计算,而直接从缓存获取计算结果呢?这就需要将该函数的返回值定义为不可变类型,如下:fromfunctoolsimportlru_cache@lru_cache(maxsize=1000,typed=True)defadd(n1,n2):print(f"计算n1+n2......")returnn1+n2r1=add(1,2)print("n1+n2={}".format(r1))r2=add(1,2)#由于该计算已经计算过,直接从缓存获取,因此值打印两次“计算n1+n2......”r3=add(3,4)+r2print("n1+n2={}".format(r3))我们可以看到r2的运算过程被跳过,而是直接从缓存中获取
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年网约车驾驶员从业资格考试题库及答案
- 2026年湖南省津市市高一化学上册期末考试模拟卷带答案(预热题)
- 2026年山东省章丘市高三生物下册期末考试模拟检测卷带答案
- 2026年山东省禹城市高一化学上册期末考试模拟试卷【含答案】
- 2026年黑龙江省肇东市高一历史下册期末考试试卷附完整答案(夺冠)
- 2026年广东省化州市高一历史下册期末考试模拟测试卷(培优B卷)附答案
- 2026年江苏省邳州市高三物理下册期末考试模拟检测卷及参考答案
- 2026年云南省安宁市高一历史下册期末考试试卷含答案【考试直接用】
- 2026年湖北省大冶市高三生物下册期末考试模拟测试卷(含答案)
- 2026年广东省开平市高三历史上册期末考试检测卷附答案(综合卷)
- 中国邮政储蓄银行2027届校园招聘笔试备考试题及答案解析
- 2025年广州市海珠区事业单位人员招聘考试试题及答案详解
- 2.7.2 勾股定理的逆定理 课件 -2026-2027学年浙教版数学八年级上册
- 2026年融媒体新闻采编技术应用及理论知识考试题库(附含答案)
- 2026国企招聘考试公共基础知识考试题(含答案)
- 髋、膝关节置换术后护理及功能康复
- 人工挖孔灌注桩安全技术交底培训
- 2025年银行考试-银行间本币市场交易员资格笔试考试历年典型考题及考点
- 内支撑设计计算书(Excel自动计算版)
- GB/T 29717-2026滚动轴承风力发电机组偏航、变桨轴承
- 新版2025-2026部编人教版小学语文1一年级上册(全册)教案设计合集
评论
0/150
提交评论