• 封装


    封装之如何调用隐藏属性

    在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

    class A:
        __x = 1     # 在类定义阶段,变量名发生了变形,变为:_类名__x(_A__x = 1)
        def __init__(self,name):
            self.__name = name    # self._A__name=name
    
        def __foo(self):     # def _A__foo(self):
            print("run foo")
    
        def bar(self):
            self.__foo()    # 在定义阶段,已将代码变为self._A__foo():
            print("from bar")
    
    
    a = A("egon")
    # print(a.__name)
    a.bar()    # 在类内部可以调用
    a._A__foo()
    

    这种变形的特点:
    1、类的外部无法直接访问obj.__AttrName
    2、在类内部是可以直接使用obj.__AttrName(在定义阶段已经改成_obj.__AttrName)
    3、子类无法覆盖隐藏的属性(__开头)

    class Foo:
        def func(self):
            print("from foo")
    
    class Bar(Foo):
        def func(self):
            print("from bar")
    
    # b = Bar()
    # b.func()
    

     子类无法覆盖父类的隐藏属性的原因

    class Foo:
        def __func(self):    # _Foo__func
            print("from foo")
    
    class Bar(Foo):
        def __func(self):    #_Bar__func
            print("from bar")

    这种变形需要注意的问题是:

    1、这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

    2、变形的过程只在类的定义是发生一次,在定义后的赋值操作,不会变形

    3、在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的


    封装的意义

    一、封装数据属性:明确的区分内外(在类内部开一个接口,调用隐藏的内容),控制外部对隐藏属性的操作

    class People:
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def tell_info(self):
            print("name:%s,age:%s"%(self.__name,self.__age))
    
        def set_info(self,name,age):
            if not isinstance(name,str):
                print("名字必须是字符串类型")
                return
            if not isinstance(age,int):
                print("年龄必须是数字类型")
                return
            self.__name = name
            self.__age = age
    
    
    p = People("alex",15)
    
    p.tell_info()
    p.set_info(123,22)

    二、封装方法:隔离复杂度

    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()
    
    a=ATM()
    a.withdraw()   # 对外无需知道内部具体的流程
    

    封装体现可扩展性

    class Room:
        def __init__(self,name,owner,weight,length,height):
            self.name = name
            self.owner = owner
            self.__weight = weight
            self.__length = length
            self.__height = height
    
        def tell_area(self):
            return self.__weight * self.__length * self.__height
    
    r = Room("卫生间","alex",10,10,10)
    print(r.tell_area())
    

    property

    通过计算才能得到的一些属性封装起来,让用户访问起来像访问数据一样,而不是像访问属性(带())形式

    例如:

    """
    成人的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
    
        @property     # 调用时不用加()
        def bmi(self):
            return self.weight / (self.height ** 2)
    
    p = People("alex",75,1.81)
    # p.bmi = p.weight / (p.height ** 2)
    print(p.bmi)    # p.bmi 本质是一种方法
    
    p.height = 1.82
    print(p.bmi)
    

     例中的p.bmi不能被赋值,若硬要赋值

    class People:
        def __init__(self,name):
            self.__name = name
    
        @property
        def name(self):
            print("getter")
            return self.__name
    
        @name.setter     # 修改 必须前面被装饰器property装饰过的
        def name(self,val):
            print("setter",val)
            if not isinstance(val,str):
                print("名字必须是字符串类型")
                return
            self.__name = val
    
        @name.deleter     # 删除 必须前面被装饰器property装饰过的
        def name(self,val):
            print("delete")
            print("不允许删除")
    
    
    p = People("alex")
    p.name
    p.name = "Jack"    # 硬要赋值的话用@函数名.setter
    print(p.name)
    

      

  • 相关阅读:
    Hidden、ViewState、ControlState 区别
    使用 CSS3 中的伪类渲染表格
    IIS与Apache
    好奇怪的问题~
    博客可长可短-UnobtrusiveValidationMode的理解
    一路走来,一些感触,一些想法
    网页中一次导出多张Excel的问题
    [Leetcode][Python]56: Merge Intervals
    [Leetcode][Python]55: Jump Game
    [Leetcode][Python]54: Spiral Matrix
  • 原文地址:https://www.cnblogs.com/fantsaymwq/p/9919048.html
Copyright © 2020-2023  润新知