封装:将类的属性隐藏
#先看如何隐藏
1,在定义的属性之前加入__.
class Foo: __N=111111 #_Foo__N def __init__(self,name): self.__Name=name #self._Foo__Name=name def __f1(self): #_Foo__f1 print('f1') def f2(self): self.__f1() #self._Foo__f1() #在类内部调用的话可以 f=Foo('egon')
#这种隐藏需要注意的问题:
#1:这种隐藏只是一种语法上变形操作,并不会将属性真正隐藏起来
# print(Foo.__dict__)
# print(f.__dict__)
# print(f._Foo__Name)
# print(f._Foo__N)
第二个问题:这种语法上的变形是在什么时候发生的
#在定义类阶段发生,并且只在这个阶段发生
比如说在上面的基础上,再定义一个Foo.__x=12121212121212121212
再去访问Foo.__x这个属性,
是可以访问的到的,不会被隐藏
第三个问题:在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
#封装不是单纯意义上的隐藏
1,封装数据属性(内部能用,外部不能用,开一个接口给其他人使用,保证代码安全性)
将属性隐藏起来,然后提供对外访问属性的接口,关键是我们在接口内定制一些控制逻辑从而严格控制对数据属性的使用
1 class People: 2 def __init__(self,name,age): 3 if not isinstance(name,str): 4 raise TypeError('%s must be str' %name) 5 if not isinstance(age,int): 6 raise TypeError('%s must be int' %age) 7 self.__Name=name 8 self.__Age=age 9 def tell_info(self): 10 print('<名字:%s 年龄:%s>' %(self.__Name,self.__Age)) 11 12 def set_info(self,x,y): 13 if not isinstance(x,str): 14 raise TypeError('%s must be str' %x) 15 if not isinstance(y,int): 16 raise TypeError('%s must be int' %y) 17 self.__Name=x 18 self.__Age=y 19 20 #p=People('egon',18) 21 #p.tell_info() 22 23 # p.set_info('Egon','19') 24 #p.set_info('Egon',19) 25 #p.tell_info()
2,封装函数属性
目标隔离复杂度。
例如ATM内部有很多负复杂的函数,内部定义,但是对于用户来说,只需要记住取款,存款这几个功能就可以了。
1 class ATM: 2 def __card(self): 3 print('插卡') 4 def __auth(self): 5 print('用户认证') 6 def __input(self): 7 print('输入取款金额') 8 def __print_bill(self): 9 print('打印账单') 10 def __take_money(self): 11 print('取款') 12 13 def withdraw(self): 14 self.__card() 15 self.__auth() 16 self.__input() 17 self.__print_bill() 18 self.__take_money() 19 20 a=ATM() 21 a.withdraw()
静态属性property:
在类里面加入这个参数以后,调用函数不用加括号了。(加括号会报错)
相当于把功能伪装成一个数据,eg:
1 class Foo: 2 @property #这里相当于把函数直接伪装了 3 def f1(self): 4 print('f1') 5 6 7 f=Foo() 8 9 # f.f1() 10 11 f.f1
写一个例子:
''' 例:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解) 成人的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 @property def bmi(self): return self.weight / (self.height**2) # p=People('egon',75,1.80) # p.height=1.86 # print(p.bmi()) #这里是在没有加property这个属性的时候用的 # print(p.bmi) #在这里就可以直接输出值了
怎么功能添加访问,设置,删除的属性。
是在函数已经设置了静态属性的前提下,在设置函数.setter,函数.deleter等属性
1 class Foo: 2 def __init__(self,x): 3 self.__Name=x 4 5 @property 6 def name(self): 7 return self.__Name 8 9 @name.setter 10 def name(self,val): 11 if not isinstance(val,str): 12 raise TypeError 13 self.__Name=val 14 15 @name.deleter 16 def name(self): 17 # print('=-====>') 18 # del self.__Name 19 raise PermissionError 20 21 # f=Foo('egon') 22 # print(f.name) 23 # 24 # # f.name='Egon' 25 # f.name=123123123213 26 # print(f.name) 27 # 28 # del f.name 29 # print(f.name)