zoukankan      html  css  js  c++  java
  • 第五章---面向对象---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

      

  • 相关阅读:
    捡来的一个大数模版。很好用
    小探catlan数
    hdu1060数学题求幂最左边的数
    食物相克
    工作 瓶颈 思路问题
    从用户态open到内核驱动实现
    内核代码 结构
    I2C原理
    asm
    man 2 3 5 普通命令(1) 函数库(3)
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/8955236.html
Copyright © 2011-2022 走看看