Python面向对象编程之类的进阶
1、引用的概念引用 (Reference)是对象的指针引用是内存中真实对象的指针表示为变量名或者内存地址每个对象存在至少一个引用id()函数用于获得引用在传递参数和赋值时Python传递对象的引用而不是复制对象示例代码:12345list1[1,2,3,4]list2list1print(id(list1))# 2044656837192print(id(list2))# 2044656837192# 因为list1是类的实例化list2引用的是list1两个都是引用的最基础的object类所以两个的结果是一样的Python内部机制对引用的处理不可变对象immutable解释器为相同值维护尽量少的内存区域可变对象mutable解释器为每个对象维护不同内存区域示例代码123456789101112text1一碗周text2text1text3一碗周text4一碗text5周text6text4text5print(id(text1))# 1616972638288print(id(text2))# 1616972638288print(id(text3))# 1616972638288print(id(text4))# 1616973621272print(id(text5))# 1616973578032print(id(text6))# 1616974246288因为text1和2是引用的一个字符串所以内存地址是一样的因为Python解释器会大可能的节省内存空间所以当不可变类型的值一样时Python会将其自动的引用一个地址空间来达到节省空间的目的所以text1/2/3的地址空间是一致的Python解释器并不会对计算出来的结果来进行地址空间的优化就算两个的值是一样的Python解释器也会为新计算出来的结果来开辟一个新的地址空间示例代码123456list1[]list2[]list3[]print(id(list1))# 3204114440776print(id(list2))# 3204114440840print(id(list3))# 3204115873544每个可变对象都有自己独立的地址空间并不复用地址空间导致引用被1的情况一般都4种对象被创建对象被引用对象被作为函数或方法的参数对象被作为一个容器中的元素导致引用-1的情况一把也都4种对象被删除对象的名字呗赋予新的对象对象离开作用域对象所在容器被删除2、对象的拷贝拷贝是复制一个对象为新对象内存空间有”变化“拷贝分为浅拷贝和深拷贝浅拷贝仅仅复制最顶层对象的拷贝方式默认拷贝方式深拷贝迭代复制所有对象的拷贝方式示例代码浅拷贝112345678910111213141516list1[甜甜, [1,2,3]]list2list1.copy()# 使用copy方法复制list3list1[:]# 使用切片复制list4list(list1)# 使用生成列表方式复制forchin[list1, list2, list3, list4]:foriinch:print(i,id(i),\t, end)# 打印列表的没一项和idprint(ch,id(ch))# 打印每个列表和id---输出结果---一碗周 2905817180184 [1, 2, 3] 2905787490888 [一碗周, [1, 2, 3]] 2905787490952一碗周 2905817180184 [1, 2, 3] 2905787490888 [一碗周, [1, 2, 3]] 2905817092488一碗周 2905817180184 [1, 2, 3] 2905787490888 [一碗周, [1, 2, 3]] 2905817137800一碗周 2905817180184 [1, 2, 3] 2905787490888 [一碗周, [1, 2, 3]] 2905817771656浅拷贝只是拷贝的列表这一层的内存空间里面的元素的内存空间不会被拷贝示例代码浅拷贝212345678910111213141516list1[一碗周, [1,2,3]]list2list1.copy()# 使用copy方法复制list3list1[:]# 使用切片复制list4list(list1)# 使用生成列表方式复制list4[1].append(4)print(list1)print(list2)print(list3)print(list4)--输出结果--[一碗周, [1, 2, 3, 4]][一碗周, [1, 2, 3, 4]][一碗周, [1, 2, 3, 4]][一碗周, [1, 2, 3, 4]]这里只对list4进行来数据的修改但是所有的列表的内容都发生了这是因为每个列表所引用的内容是一样的所以修改了1个四个会发生改变深拷贝要采用copy库里面的deepcopy()方法迭代拷贝对象内层的各层次对象完全新开辟内存空间建立对象以及对象下层的各种对象元素深拷贝仅仅针对可变类别不可变类型不许创建新对象示例代码12345678910111213importcopy# 导入库list1[一碗周, [1,2,3]]list2copy.deepcopy(list1)# 使用copy库的deepcopy方法复制forchin[list1, list2]:foriinch:print(i,id(i),\t, end)# 打印列表的没一项和idprint(ch,id(ch))# 打印每个列表和id---输出结果---一碗周 2190823984184 [1, 2, 3] 2190853845832 [一碗周, [1, 2, 3]] 2190853766728一碗周 2190823984184 [1, 2, 3] 2190853961544 [一碗周, [1, 2, 3]] 2190853961480因为“甜甜”字符串属于不可变类型所以其地址空间不会发生改变剩下的地址空间都发生了改变2.1 实例方法的引用实例方法也是一种引用就是对象本身的引用当方法被引用时方法即函数将产生一个对象方法对象2.2 类的特性装饰器property装饰器可以把方法改变成对外可见的”属性“在类内部表现为方法在外边表现为属性示例代码123456789101112131415161718192021classTestClass:def__init__(self, name):self.namenameproperty# 将方法转换为属性defage(self):returnself.__ageage.setter# 为属性进行赋值操作defage(self, value):ifvalue 0orvalue 110:value19self.__agevaluettTestClass(一碗周)bbTestClass(一碗粥)tt.age18bb.age-19print(tt.age)# 18print(bb.age)# 193、类的名称修饰名称修饰 (Name Mangling)是类中名称的转换约定Python可以通过名称修饰来完成一些重要功能在Python中采用下划线_来进行名称修饰分为5种情况_namename___name__name___3.1 _单下划线开头的名称修饰单下划线开头属性或者方法为类内部使用的约定是PEP8规定的一种约定只是约定依然可以通过对象名.属性名方式访问在功能的上的不同是使用from XX import*时不会导入单下划线开头的属性或者方法示例代码1234567classTestClass:def__init__(self, name):self._namename# 约定在内部使用ttTestClass(一碗周)print(tt._name)# 一碗周虽然约定在内部使用但是依然可以被访问3.2 _单下划线结尾的名称修饰单下划线结尾的属性或者方法是避免与保留字或已有命名冲突这也是PEP8规定的这仅仅是一个约定没有任何对应的功能