Python3 从零单排18_封装
隐藏属性
# 申明类时,数据属性或者函数属性,在属性名称前加上两个下划线,就实现了属性隐藏,但在python里不存在绝对的隐藏,它只是在申明的时候定义了它的调用方式。 class A: __country = "china" def __def(self): print(self.__country) a = A() print(a.__country) # 报错,这是隐藏属性 print(a._A__country) # 对的,python里不会绝对隐藏,只是在类命名的时候定义了新的访问方式,需要在隐藏变量名前加 "_类名" 就可以访问 print(A.__dict__) # 可以看到在类A的属性字典里有一个kv是'_A__country': 'china',隐藏的函数属性也一样的道理 # 当然python只是没有绝对隐藏,但是如果加上了隐藏属性,一般不会像上面那样去访问,那这个有什么用呢? # 1.防止属性被改写 2.防止类内部在调用属性的时候调用到别的类的属性 class A: def func1(self): print("i am func1 from A") def __func2(self): print("i am func2 from A") def func3(self): print("i am func3 from A") self.func1() # b调用时,这里实际是 b.func1(),那么他先会在B类里找func1,所以这里会打印("i am func1 from B") self.__func2() # b调用时,这里实际是 b._A__func1(),那么找到的就是A类里的__func2,所以这里会打印("i am func2 from A") class B(A): def func1(self): print("i am func1 from B") def __func2(self): # 这里并不是改写父类A的__func2,因为这里已经变成了,_B__func2 print("i am func2 from A") b = B() b.func3()
封装数据属性:明确的区分内外,控制外部对隐藏的属性的操作行为
class People: def __init__(self,name,age): self.__name=name self.__age=age def tell_info(self): print('Name:<%s> Age:<%s>' %(self.__name,self.__age)) def set_info(self,name,age): if not isinstance(name,str): print('名字必须是字符串类型') return if not isinstance(age,int): print('年龄必须是数字类型') return self.__name=name self.__age=age p=People('egon',18) # p.tell_info() # p.set_info('EGON',38) # p.tell_info() # p.set_info(123,38) p.set_info('egon','38') p.tell_info()
封装方法:隔离复杂度
class ATM: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入取款金额') def __print_bill(self): print('打印账单') def __take_money(self): print('取款') def withdraw(self): self.__card() self.__auth() self.__input() self.__print_bill() self.__take_money() a = ATM() a.withdraw()
property 将函数属性变成数据属性,但只是像数据属性,并不是真的数据属性,在重新赋值的时候会报错。
class People: def __init__(self,name,weight,height): self.name=name self.weight=weight self.height=height @property def bmi(self): return self.weight / (self.height ** 2) p=People('xg',60,168) # print(p.bmi) # p.bmi=3333 #报错AttributeError: can't set attribute # 但是有一些方法可以修改和删除这些属性。 class A: def __init__(self, name): self.__name = name @property def name(self): return self.__name @name.setter def name(self, name): # 修改被property装饰的函数属性,直接 a.name = new_name 即可 self.__name = name @name.deleter def name(self): # 删除 a.name ,直接 del a.name 即可 print("不可以删除") a = A("xg") print(a.name) a.name = "XG" print(a.name) del a.name print(a.name)
夕闻道不如朝闻道