20--封装、隐藏属性、property装饰器
2022/6/27 6:23:46
本文主要是介绍20--封装、隐藏属性、property装饰器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1 封装介绍
# 一、封装介绍 面向对象编程有三大特性:封装、继承、多态 封装是面向对象三大特性最核心的一个特性 封装 就是 整合
2 隐藏属性
2.1 如何隐藏
# 如何隐藏:在属性名前加__前缀,就会实现一个对外隐藏属性效果 class Foo: __x = 1 # _Foo__x def __f1(self): # _Foo__f1 print('from test') print(Foo.__dict__) print(Foo._Foo__x) print(Foo._Foo__f1) # 该隐藏需要注意的问题: # 1.在类外部无法直接访问双下滑线开头的属性 但知道了类名和属性名就可以拼出名字:_类名__属性, 然后就可以访问了,如Foo._A__N, 以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。 # 2.这种隐藏对外不对内,因为__开头的属性会在检查类体代码语法时统一发生变形 (内部可以正常使用) class Foo: __x = 1 # _Foo__x = 1 def __f1(self): # _Foo__f1 print('from test') def f2(self): print(self.__x) # print(self._Foo__x) print(self.__f1) # print(self._Foo__f1) print(Foo.__x) print(Foo.__f1) obj=Foo() obj.f2() # 3.这种变形操作只在检查类体语法的时候发生一次,之后定义的__开头的属性都不会变形 Foo.__y=3 # 添加类__y 属性 print(Foo.__dict__) # Foo.__y没有变形 print(Foo.__y) # 3 # 对象的独有属性 隐藏 一样的方法,变量名前 加 '__' class Foo: __x = 1 # _Foo__x = 1 def __init__(self,name,age): self.__name=name self.__age=age obj=Foo('egon',18) print(obj.__dict__) print(obj.name,obj.age) # 报错,找不到
2.2 为何隐藏属性
# 1.隐藏数据属性 将数据隐藏起来就限制了类外部对数据的直接操作 然后类内应该提供相应的接口来允许类外部间接地操作数据, 接口之上可以附加额外的逻辑来对数据的操作进行严格地控制 # 设计者:egon class People: def __init__(self, name): self.__name = name def get_name(self): # 通过该接口就可以间接地访问到名字属性 # print('小垃圾,不让看') print(self.__name) def set_name(self,val): if type(val) is not str: print('小垃圾,必须传字符串类型') return self.__name=val # 使用者:王鹏 obj = People('egon') print(obj.name) # 无法直接用名字属性,必须通过设计者开发的接口来访问 (也防止了使用者可以任意修改) obj.set_name('EGON') obj.set_name(123123123) # 限制外部,逻辑控制 obj.get_name() # 2.隐藏函数/方法属性:目的的是为了隔离复杂度 (降低复杂度,方便使用) 例如ATM程序的取款功能,该功能有很多其他功能组成 比如插卡、身份认证、输入金额、打印小票、取钱等, 而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来
3 property 装饰器
装饰器是在不修改被装饰对象源代码以及调用方式的前提下 为被装饰对象添加新功能的可调用对象 # property是一个装饰器,是用来把绑定给对象的方法 伪造成一个数据属性 # 案例一: 直接将方法,伪装成数据属性 """ 成人的BMI数值: 过轻:低于18.5 正常:18.5-23.9 过重:24-27 肥胖:28-32 非常肥胖, 高于32 体质指数(BMI)=体重(kg)÷身高^2(m) EX:70kg÷(1.75×1.75)=22.86 """ class People: def __init__(self, name, weight, height): self.name = name self.weight = weight self.height = height # 定义函数的原因: 1.从bmi的公式上看,bmi应该是触发功能计算得到的 2.bmi是随着身高、体重的变化而动态变化的,不是一个固定的值 说白了,每次都是需要临时计算得到的 # 但是bmi听起来更像是一个数据属性,而非功能 @property def bmi(self): return self.weight / (self.height ** 2) obj1 = People('egon', 70, 1.83) print(obj1.bmi()) # 加上property装饰器后,访问对象的方法 (调用函数的形式) 变成了 访问对象的数据属性 print(obj1.bmi) # 案例二: # 前提: 将原本 对象的方法(一般三种:查、改、删) 隐藏后变成了 数据属性 但使用者的正常逻辑还是访问数据的形式,故使用property 变成数据属性 # 方式一:直接调用 property 函数的形式,将方法 传参给property函数 name = property(get_name,set_name,del_name) class People: def __init__(self, name): self.__name = name def get_name(self): return self.__name def set_name(self, val): if type(val) is not str: print('必须传入str类型') return self.__name = val def del_name(self): print('不让删除') # del self.__name name=property(get_name,set_name,del_name) obj1=People('egon') # 使用前 print(obj1.get_name()) obj1.set_name('EGON') obj1.del_name() # 使用后 print(obj1.name) obj1.name = 18 del obj1.name # 方式二: 使用property 装饰器的形式 *********** class People: def __init__(self, name): self.__name = name @property def name(self): # obj1.name return self.__name @name.setter def name(self, val): # obj1.name='EGON' if type(val) is not str: print('必须传入str类型') return self.__name = val @name.deleter def name(self): # del obj1.name print('不让删除') # del self.__name obj1=People('egon') print(obj1.name) obj1.name=18 del obj1.name
这篇关于20--封装、隐藏属性、property装饰器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?
- 2024-05-09企业src漏洞挖掘-有意思的命令执行
- 2024-05-08阿里云域名注册流程,分享给第一次购买域名的新手站长!