第五章---面向对象---1.封装之如何实现属性的隐藏/2.封装的意义/3.封装与扩展性/4.property的使用
Posted mumupa0824
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第五章---面向对象---1.封装之如何实现属性的隐藏/2.封装的意义/3.封装与扩展性/4.property的使用相关的知识,希望对你有一定的参考价值。
1.封装之如何实现属性的隐藏
封装: __x=1 # 把数据属性隐藏 (如何实现隐藏) 类定义阶段 __开头发生了变形 __x --> _A__x
特点:
1.在类外部无法直接:obj.__AttrName
2.在类内部是可以直接使用:obj.__AttrName # 为什么会这样?python 如何实现的 !类定义阶段已经变形 #__x --> _A__x #self._A_foo()
3.子类无法覆盖父类__开头的属性 它两根本不是一个名字 #_Foo__func #_Bar__func
总结:
这种变形需要注意的问题:
1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N eg:print(A._A__x)
2.变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形 eg: b.__age=18 {‘_B__name‘: ‘alice‘, ‘__age‘: 18}
3.在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的 eg: def __foo(self): #_A__foo
1 # class A: 2 # __x = 1 # 把数据属性隐藏 _A__x = 1 3 # 4 # def __init__(self,name): 5 # self.__name = name # self._A__name = name 6 # 7 # def __foo(self): # 把函数属性隐藏 def _A__foo(self): 8 # print(‘run foo‘) 9 # 10 # def bar(self): 11 # self.__foo() # self._A__foo() # 类内部访问时已经变形了 12 # print(‘from bar‘) 13 # 14 # print(A.__dict__) 15 16 # {‘__module__‘: ‘__main__‘, ‘_A__x‘: 1, ‘__init__‘: <function A.__init__ at 0x0000017AC92B0B70>, ‘_A__foo‘: <function A.__foo at 0x0000017AC92B0BF8>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘A‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘A‘ objects>, ‘__doc__‘: None} 16 # 17 # 18 # print(A.__x) 19 # print(A.__foo) 20 21 # a = A(‘egon‘) 22 #print(a.__name) 23 24 # print(A.__dict__) 25 # print(a.__dict__) 26 27 # a.bar() 28 # run foo 29 # from bar 30 31 --------------------------------------------------------- 32 33 # class Foo: 34 # def func(self): 35 # print(‘from foo‘) 36 # 37 # class Bar(Foo): 38 # def func(self): 39 # print(‘from bar‘) 40 # 41 # b = Bar() 42 # b.func() 43 # # from bar 44 45 # class Foo: 46 # def __func(self): #_Foo__func 47 # print(‘from foo‘) 48 # 49 # class Bar(Foo): 50 # def __func(self): # _Bar__func 51 # print(‘from bar‘) 52 53 ------------------------------------------------------- 54 55 # class B: 56 # __x = 1 57 # 58 # def __init__(self,name): 59 # self.__name = name 60 61 # 验证问题一: 62 # print(B._B__x) 63 64 # 验证问题二: 65 # B.__y = 2 66 # print(B.__dict__) 67 # {‘_B__x‘: 1, ‘__y‘: 2, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘B‘ objects>, 68 # ‘__module__‘: ‘__main__‘, ‘__doc__‘: None, ‘__init__‘: <function B.__init__ at 0x023B02B8>, 69 # ‘__dict__‘: <attribute ‘__dict__‘ of ‘B‘ objects>} 70 # b = B(‘egon‘) 71 # print(b.__dict__) 72 # # {‘_B__name‘: ‘egon‘} 73 # 74 # b.__age = 18 75 # print(b.__dict__) 76 # # {‘_B__name‘: ‘egon‘, ‘__age‘: 18} 77 78 # 验证问题三: 79 # class A: 80 # def foo(self): 81 # print(‘A.foo‘) 82 # def bar(self): 83 # print(‘A.bar‘) 84 # self.foo() # b.foo() 85 # 86 # class B(A): 87 # def foo(self): 88 # print(‘B.foo‘) 89 # 90 # b = B() 91 # b.bar() 92 93 # A.bar 94 # B.foo 95 96 class A: 97 def __foo(self): #_A_foo 98 print(‘A.foo‘) 99 def bar(self): 100 print(‘A.bar‘) 101 self.__foo() # self._A__foo() 102 103 class B(A): 104 def __foo(self): # _B__foo 105 print(‘B.foo‘) 106 107 b = B() 108 b.bar() 109 110 # A.bar 111 # A.foo
2.封装的意义
封装数据属性目的: (封装不是单纯意义上的隐藏)
明确的区分内外,控制外部对隐藏的属性的操作行为
封装方法属性目的:
隔离复杂度 # a=ATM() a.withdraw()
1 # 1.封装数据属性:明确的区分内外,控制外部对隐藏的属性的操作行为 2 # class People: 3 # def __init__(self,name,age): 4 # self.__name = name 5 # self.__age = age 6 # 7 # def tell_info(self): 8 # print(‘Name:<%s> Age:<%s>‘ % (self.__name,self.__age)) 9 # 10 # def set_info(self,name,age): 11 # if not isinstance(name,str): 12 # print(‘名字必须是字符串类型‘) 13 # return 14 # if not isinstance(age,int): 15 # print(‘年龄必须是数字类型‘) 16 # return 17 # self.__name = name 18 # self.__age = age 19 # p = People(‘egon‘,18) 20 # p.tell_info() 21 # # p.set_info(‘EGON‘,38) 22 # p.set_info(‘EGON‘,‘18‘) 23 # p.tell_info() 24 25 # 2.封装方法的目的:隔离复杂度 26 27 class ATM: 28 def __card(self): 29 print(‘插卡‘) 30 def __auth(self): 31 print(‘用户认证‘) 32 def __input(self): 33 print(‘输入取款金额‘) 34 def __print_bill(self): 35 print(‘打印账单‘) 36 def __take_money(self): 37 print(‘取款‘) 38 39 def withdraw(self): 40 self.__card() 41 self.__auth() 42 self.__input() 43 self.__print_bill() 44 self.__take_money() 45 46 a=ATM() 47 a.withdraw()
3.封装与扩展性
面向对象:可扩展性高
面向对象三大特性:继承 多态 封装
封装的扩展性:
def tell_area(self): # 对使用者来说 不用改变 方式 开发者在类里面修改
class Room: def __init__(self,name,owner,weight,length): self.name = name self.owner = owner self.__weight = weight self.__length = length def tell_area(self): # 对使用者来说 不用改变方式 return self.__weight * self.__length r = Room(‘卫生间‘,‘alex‘,10,10) print(r.tell_area())
4.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
-------------------------------
property :
@property
def bmi(self): 必须有个返回值
print(p.bmi) 可以使 函数属性 伪装成 数据属性 bmi 是名词
p.bmi=23 # 不能赋值 can‘t set attribute bmi 实质是个方法
总结:通过计算得来的方法 可以通过@property 伪装成数据属性
@property 查看 必须有返回值
@name.setter 修改
@name.deleter 删除
1 # class People: 2 # def __init__(self,name,weight,height): 3 # self.name=name 4 # self.weight=weight 5 # self.height=height 6 # 7 # @property 8 # def bmi(self): # 必须要有个返回值 9 # return self.weight / (self.height ** 2) 10 # 11 # p=People(‘egon‘,75,1.81) 12 # p.bmi=p.weight / (p.height ** 2) 13 # print(p.bmi) 14 15 # print(p.bmi()) # 函数 是 去做什么! 是动词 对于使用者 产生误解 调了一个动词 16 17 # print(p.bmi) # 使用者可以像 访问数据属性 那样 访问 函数属性 18 # p.height=1.82 19 # print(p.bmi) 20 # p.bmi=33 # 不能赋值 can‘t set attribute bmi 实质是个方法 21 22 # ------------------------------------------------------------ 23 class People: 24 def __init__(self,name): 25 self.__name=name 26 27 @property # 查看 28 def name(self): 29 # print(‘getter‘) 30 return self.__name 31 32 @name.setter # 修改 # 前提是 一定被装饰过 property 33 def name(self,val): 34 # print(‘setter‘,val) 35 if not isinstance(val,str): 36 print(‘名字必须是字符串‘) 37 return 38 self.__name=val 39 40 @name.deleter # 删除 41 def name(self): 42 # print(‘deleter‘) 43 print(‘不允许删除‘) 44 45 46 p=People(‘alice‘) 47 # print(p.name) 48 49 # p.name=‘alex‘ 50 # print(p.name) 51 52 del p.name
以上是关于第五章---面向对象---1.封装之如何实现属性的隐藏/2.封装的意义/3.封装与扩展性/4.property的使用的主要内容,如果未能解决你的问题,请参考以下文章