第五章---面向对象---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的使用的主要内容,如果未能解决你的问题,请参考以下文章

java第五章:面向对象(oop)之三大特性

第五章,面向对象基础篇

第五章 面向对象编程设计与开发——续3

第五章.面向对象(上)

java第五章:面向对象(oop)三大特性之多态

第二十五章 面向对象------封装内置函数反射动态导入