封装
1\ 封装
在Python中没有真正的隐藏,只有语法级别的限制,可以通过类名还可以查看数据
1 #封装数据 2 #封装功能 3 class Teacher: 4 __school='oldboy' #_Teacher__school 5 def __init__(self,name,salary): 6 self.name=name 7 self.__salary=salary #self._Teacher__salary 8 9 def __foo(self): 10 print('====>') 11 t=Teacher('egon',3000) 12 13 #print(t.__school) 14 # print(Teacher.__dict__) 15 16 #t.foo() #封装后,无法查看,但可以通过类 的属性来查看 17 # t._Teacher__foo() # ====> 18 # 19 # 20 #print(t.salary) 21 #print(t.__salary) 22 print(t.__dict__)#{'name': 'egon', '_Teacher__salary': 3000} 23 # 24 print(t._Teacher__salary)#3000 25 26 #这种变形操作只在定义阶段发生 27 Teacher.__N=111111 28 print(Teacher.__dict__) 29 30 # 31 t.__x=1 32 print(t.__dict__)
1 #在类的外部,无法直接使用变形的属性,但是在类的内部可以直接使用 2 class Teacher: 3 __school='oldboy' #_Teacher__school='oldboy' 4 def __init__(self,name,salary): 5 self.name=name 6 self.__salary=salary #self._Teacher__salary=salary 7 8 def foo(self): 9 print('====>',self.__salary) 10 # print('====>',self._Teacher__salary) 11 t=Teacher('egon',3000) 12 13 # print(t.__salary) 14 t.foo() #====> 3000
2\对象通过父类调用封装的函数属性,
1 class Foo: 2 def __func(self): #_Foo__func 3 print('from Foo') 4 5 class Bar(Foo): 6 def __func(self): #_Bar__func 7 print('from Bar') 8 9 10 11 b=Bar() 12 #b.func() #被封装,找不到, 报错 AttributeError: 'Bar' object has no attribute 'func' 13 b._Foo__func()#from A.foo 对象通过父类调用父类的函数 14 b._Bar__func()#from A.bar 对象通过类名调用类的函数
1 class A: 2 def foo(self): 3 print('from A.foo') 4 self.__bar() #self._A__bar() 5 6 7 def __bar(self): #_A__bar() 8 print('from A.bar') 9 10 class B(A): 11 def __bar(self): #_B__bar 12 print('from B.bar') 13 pass 14 15 b=B() 16 b.foo()#from A.foo from A.bar 17 # 要调用foo()属性,b本身的对象没有foo(),就从B类里面找,B类里面也没有,从A类里找,有,打印'from A.foo',同时又找到了self.__bar() 18 #函数,执行print('from B.bar')
3\用户的数据封装后,用户查看信息,同时可以修改,在修改前加上逻辑判断
1 class People: 2 def __init__(self,name,age,sex,height,weight): 3 self.__name=name 4 self.__age=age 5 self.__sex=sex 6 self.__height=height 7 self.__weight=weight 8 9 def tell_name(self): 10 print(self.__name) 11 12 def set_name(self,val): #set_name就是提高了一个接口,用于用户修改个人信息 13 if not isinstance(val,str): #加上了逻辑判断,用户输入的必须是字符串,不是,就触发报错 14 raise TypeError('名字必须是字符串类型') 15 self.__name=val #如果输入的是字符串,就添加 16 17 def tell_info(self): 18 print(''' 19 ---------%s info 20 name:%s 21 age:%s 22 sex:%s 23 height:%s 24 weight:%s 25 ''' %(self.__name, 26 self.__name, 27 self.__age, 28 self.__sex, 29 self.__height, 30 self.__weight)) 31 32 egon=People('egon',18,'male','179cm','70kg') 33 #egon.tell_info() 34 35 # ---------egon 36 # info 37 # name:egon 38 # age: 18 39 # sex: male 40 # height: 179 41 # cm 42 # weight: 70 43 # kg 44 45 46 47 # 48 egon.set_name('林大昆') 49 # egon.set_name(123123123) # raise TypeError('名字必须是字符串类型'),,TypeError: 名字必须是字符串类型 50 51 egon.tell_info() 52 53 #修改后的用户信息 54 # ---------林大昆 55 # info 56 # name:林大昆 57 # age: 18 58 # sex: male 59 # height: 179 60 # cm 61 # weight: 70 62 # kg
4\ property的装饰器使用
1 class People: 2 def __init__(self,name,age,sex,height,weight): 3 self.__name=name 4 self.__age=age 5 self.__sex=sex 6 self.__height=height 7 self.__weight=weight 8 # 9 # def tell_bmi(self): 10 # res = self.__weight / (self.__height ** 2) 11 # print('name:%s bmi:%s' % (self.__name, res)) 12 13 @property # property是把函数的属性装饰成数据属性,直接用,不加括号 14 def bmi(self): 15 res=self.__weight / (self.__height ** 2) 16 return res 17 print('name:%s bmi:%s' %(self.__name,res)) 18 #bmi=property(bmi) 19 20 def tell_name(self): 21 print(self.__name) 22 23 def set_name(self,val): 24 if not isinstance(val,str): 25 raise TypeError('名字必须是字符串类型') 26 self.__name=val 27 28 def tell_info(self): 29 print(''' 30 ---------%s info 31 name:%s 32 age:%s 33 sex:%s 34 height:%s 35 weight:%s 36 ''' %(self.__name, 37 self.__name, 38 self.__age, 39 self.__sex, 40 self.__height, 41 self.__weight)) 42 43 egon=People('egon',18,'male',1.79,70) 44 # egon.tell_info() 45 # 46 # egon.tell_name() 47 48 # egon.tell_info() 49 50 # egon.set_name('林大昆') 51 # egon.set_name(123123123) 52 # egon.tell_info() 53 54 #egon.tell_bmi() #通过tell_bmi函数接口直接调用了结果 55 print(egon.bmi) #21.847008520333322
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
在Python中,数据都是私有的,提供接口取获取和设置,通过property的方法实现
class People: def __init__(self,name,age,sex,height,weight,permission=False): self.__name=name self.__age=age self.__sex=sex self.__height=height self.__weight=weight self.permission=permission @property def name(self): return self.__name @name.setter #修改姓名,,做逻辑判断 def name(self,val): if not isinstance(val,str): raise TypeError('must be str') self.__name=val @name.deleter #删姓名,做 def name(self): if not self.permission: raise PermissionError('不让删') del self.__name egon=People('egon',18,'male',1.79,70) # print(egon.name) #egon.name=123 #修改姓名,必须为字符串才行 # print(egon.name) # print(egon.permission) egon.permission=True del egon.name #删除姓名 egon.name='alex' #给姓名再赋值 print(egon.name)