zoukankan      html  css  js  c++  java
  • 面向对象-封装实现属性隐藏

    封装原理与特性

    隐藏属性:在变量或函数前面加__符号

    class A:
        __x=1
        def __init__(self,name):
            self.__name=name
        def __foo(self):
            print('run foo')
    print(A.__x)

    print(A.__dict__)

    在类定义阶段就,已经改名字。即检测语法的时候已经变形。

    在类的内部可以直接调用

    class A:
        __x=1
        def __init__(self,name):
            self.__name=name
        def __foo(self):
            print('run foo')
        def bar(self):
            self.__foo()
            print('from bar')
    a=A('ya')
    a.bar()

     正常情况下,子类可以重写父类方法

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

    但是父类方法隐藏后,子类无法重写父类方法

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

    变形特点

    • 在类的外部无法直接通过obj.__AttrName来访问
    • 在类的内部可以直接使用obj.__AttrName来访问
    • 子类无法重写父类方法,即子类无法覆盖父类__开头的属性

    变形注意的问题:

    • 这种隐藏不是真正的隐藏
    • 变形在类定义阶段发生,定义后再给类添加隐藏属性,则无法达到‘隐藏’效果
    • 在继承中,如果父类不想子类重写方法,可用__设置称私有的,使其无法修改

    封装的意义

    封装数据属性:明确区分内外,在内部定义接口,使其外部间接访问,也可定义修改接口,可以在接口上添加逻辑,进行控制。

    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))
    p=People('ya',18)
    p.tell_info()

    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('ya',18)
    p.tell_info()
    p.set_info('Hyaya','19')
    p.tell_info()

    封装方法:隔离复杂度

    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()

    类外部用户无需单独一步一步执行__方法,只需调用withdraw()方法即可

    封装与扩展

    class Room:
        def __init__(self,name,owner,height,weight,length):
            self.name=name
            self.owner=owner
            #将长宽高设置为隐藏
            self.__height=height
            self.__weight=weight
            self.__length=length
        def tell_area(self):
            return self.__weight * self.__length
    r=Room('卫生间','xxx',10,10,10)
    print(r.tell_area())

    用户可以随意修改tell_area()方法,对于用户的调用,无需干涉。

    property的使用

    把通过计算才能获得值得方法封装称属性方式,调用无需添加()符号

    装饰后,调用数据属性的方式调用方法属性,但是不可直接像数据属性一样赋值

    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('egon',80,1.6)
    print(p.bmi)

    p=People('egon',80,1.6)
    p.bmi=22
    print(p.bmi)

    对方法属性再次控制

    class People:
        def __init__(self,name):
            self.__name=name
        @property
        def name(self):
            return self.__name
        @name.setter
        def name(self,val):
            if not isinstance(val,str):
                print(("名字必须为字符串"))
                return
            self.__name=val
        @name.deleter
        def name(self):
            print('名字属性不让删除')
    p=People('ya')
    p.name="YA"
    print(p.name)
    del p.name

  • 相关阅读:
    pytest-multithreading实现并发运行(可以指定不参与并发的case)
    python 命令行传参方式结合jenkins构建时选择环境
    pytest结合ReportPortal使用
    loguru日志
    httprunner3 log放到allure中显示
    pytest
    python
    Mac下安装docker
    USC提出拟牛顿法深度学习优化器Apollo,效果比肩SGD和Adam
    28例电气自动控制电路图,快收藏!
  • 原文地址:https://www.cnblogs.com/yaya625202/p/8879534.html
Copyright © 2011-2022 走看看