面向对象之封装
一.引子
封装不等同于隐藏。
二.隐藏
2.1如何把属性隐藏起来?
就在属性前面加上__开头(注意不要加__结尾)
class Foo: x=111 def __init__(self,y): self.__y=y#属性前加__ def __f1(self): print('Foo,f1') obj=Foo(2222) print(obj.y)#'Foo' object has no attribute 'y' print(Foo.x)
2.2加上__开头到底发生了什么事情,从而访问不到属性
python中的隐藏其实是一种语法的变形
class Foo: __x=1111 def __init__(self,y): self.__y=y#属性前加__ def __f1(self): print('Foo,f1') obj=Foo(2222) print(Foo.__dict__)#查看类的结构 print(obj._Foo__x)#查看出隐藏的属性 print(obj._Foo__y)
# 注意: #1、其实这种隐藏只是一种语法上的变形,对外不对内 # 为一个属性名加__开头(注意不要加__结尾),会在类定义阶段将属性名统一变形:_自己的类名__属性名
三.封装不是单纯意义上的隐藏
3.1什么是封装
装就是把一堆属性存起来,封的概念就把这些属性给隐藏起来
强调:封装单从字面意思去看等同于隐藏,但其实封装绝对不是单纯意义的隐藏
pass
1.11什么是封装
装就是把一堆属性存起来,封的概念就把这些属性给隐藏起来
强调:封装单从字面意思去看等同于隐藏,但其实封装绝对不是单纯意义的隐藏
1.12为什么要用封装
''' #1 封装数据属性的目的:把数据属性封装起来,然后需要开辟接口给类外部的使用者使用,好处是 # 我们可以在接口之上添加控制逻辑,从而严格空间访问者对属性的操作 # class People: # def __init__(self,name,age): # self.__name=name # self.__age=age # # def tell_info(self): # # u=input('user>>: ').strip() # # p=input('pwd>>: ').strip() # # if u == 'egon' and p == '123': # print(self.__name,self.__age) # # def set_info(self,name,age): # if type(name) is not str: # raise TypeError('用户名必须为str类型') # if type(age) is not int: # raise TypeError('年龄必须为int类型') # self.__name=name # self.__age=age # # p=People('egon',18) # # # p.tell_info() # # p.tell_info() # # # p.set_info('EGON',19) # # p.tell_info() # # # p.set_info(353535353535353535,20) # p.set_info('EGON','20') #2 封装函数属性的目的:为了隔离复杂度 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() obj=ATM() obj.withdraw() #封装的终极奥义:明确地区分内外,对外是隐藏的,对内是开放的
1.13如何用封装
# 如何把属性隐藏起来,就在属性前面加上__开头(注意不要加__结尾) # 注意: #1、其实这种隐藏只是一种语法上的变形,对外不对内 # 为一个属性名加__开头(注意不要加__结尾),会在类定义阶段将属性名统一变形:_自己的类名__属性名 class Foo: __x=1111 #_Foo__x=1111 def __init__(self,y): self.__y=y #self._Foo__y=y def __f1(self): #_Foo__f1 print('Foo.f1') def get_y(self): print(self.__y) # print(self._Foo__y) obj=Foo(22222) # print(obj.x) # print(obj.__x) # obj.__f1() # print(obj.y) # print(obj.__y) # print(Foo.__dict__) # print(obj._Foo__x) # print(obj._Foo__y) # obj._Foo__f1() # obj.get_y() #2、这种语法意义上变形,只在类定义阶段发生一次,类定义之后,新增的__开头的属性都没有变形的效果 # Foo.__aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1 # print(Foo.__dict__) # obj.__bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=2 # print(obj.__dict__) #3、如果父类不想让子类覆盖自己的方法,可以在方法名前加__开头 class Foo: def __f1(self): #_Foo__f1 print('Foo.f1') def f2(self): print('Foo.f2') self.__f1() #obj._Foo__f1() class Bar(Foo): def __f1(self): #_Bar__f1 print("Bar.f1") obj=Bar() obj.f2()
2.1封装之property
property实际应用
''' 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 def bmi(self): return self.weight/(self.height*self.height) # 首先需要明确。bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能 #都会立即计算一个值 egon=People('egon',75,1.80) yl=People('yangli',85,1.74) # 但很明显人的bmi值听起来更像一个名词而非动词 print(egon.bmi()) print(yl.bmi())
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*self.height) # 首先需要明确。bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能 #都会立即计算一个值 egon=People('egon',75,1.80) yl=People('yangli',85,1.74) # 但很明显人的bmi值听起来更像一个名词而非动词 print(egon.bmi) print(yl.bmi)
property的增删改查
# 了解 # egon.bmi=123 # egon.bmi背后对应的是一个函数,所以不能赋值 class People: def __init__(self,name): self.__name=name @property def name(self): #obj.name print('您现在访问的是用户名。。。') return self.__name @name.setter #obj.name='EGON' def name(self,x): # print('=================',x) if type(x) is not str: raise TypeError('名字必须是str类型,傻叉') self.__name=x @name.deleter def name(self): # print('就不让你删') del self.__name obj=People('egon') #增删改查 # print(obj.name) # print(obj.name()) # print(obj.name) # obj.name='EGON' # print(obj.name) # obj.name=123 del obj.name obj.name