zoukankan      html  css  js  c++  java
  • 面向对象-封装

    一、封装如何隐藏属性

    class A:
        __x=1
    
        def __init__(self,name):
            self.__name=name # self._A__name=name
    
        def __foo(self): # def _A__foo(self):
            print('run foo')
    
    
    # print(A.__x) # 没有这个值了
    
    a = A('egon')
    print(a.__dict__)  # {'_A__name': 'egon'}
    这种变形特点:
    1、外部无法直接访问到 obj.__AttrName
    2、在类内部 obj.__AttrName
    3、子类无法覆盖父类 __开头的属性(根本不是一个名字)
    class Foo:
        def __func(self): # _Foo__func(self)
            print('from foo')
    
    class Bar(Foo): # _Bar__func(self):
        def __func(self):
            print('from bar')
    总结:
    1、隐藏只在函数定义的时候才会发生
    2、加上__ 后 只能在自己或者自己类里找
    class B:
        __x=1
    
        def __init__(self,name):
            self.__name=name
    
    print(B._B__x)
    B.__y=2
    print(B.__dict__)
    
    #1.常态
    class A:
        def foo(self):
            print('A.foo')
    
        def bar(self):
            print('A.bar')
            self.foo()
    
    class B(A):
        def foo(self):
            print('B.foo')
    
    b=B()
    b.bar()  # A.bar  B.foo
    
    #2.隐藏用法:只调取自己类的,不调取其他类的
    class A:
        def __foo(self): # _A__foo
            print('A.foo')
    
        def bar(self):
            print('A.bar')
            self.__foo() # self._A__foo()
    
    class B(A):
        def __foo(self): #_B__foo
            print('B.foo')
    
    b=B()
    b.bar()  # A.bar  A.foo

    二、封装的意义

    封装数据属性:明确区分内外,控制外部对隐藏的属性的应用
    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('egon',18)
    
    # p.tell_info()
    
    # p.set_info('EGON',18)  # 修改为这两个值
    # p.tell_info()  # 间接调取
    
    p.set_info(123,18)
    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()

    特性(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)
    
    p1=People('egon',52,1.67)
    print(p1.bmi)

    将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

    @property 封装逻辑,像是在调取一个普通属性,隐藏了内部逻辑,外观看着像是调取普通的属性。

    封装与拓展性

    封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;

    而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。

    这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

    #类的设计者
    class Room:
        def __init__(self,name,owner,width,length,high):
            self.name=name
            self.owner=owner
            self.__width=width
            self.__length=length
            self.__high=high
        def tell_area(self): #对外提供的接口,隐藏了内部的实现细节,此时我们想求的是面积
            return self.__width * self.__length
    
    
    #使用者
    >>> r1=Room('卧室','egon',20,20,20)
    >>> r1.tell_area() #使用者调用接口tell_area
    400
    
    
    #类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
    class Room:
        def __init__(self,name,owner,width,length,high):
            self.name=name
            self.owner=owner
            self.__width=width
            self.__length=length
            self.__high=high
        def tell_area(self): #对外提供的接口,隐藏内部实现,此时我们想求的是体积,内部逻辑变了,只需求修该下列一行就可以很简答的实现,而且外部调用感知不到,仍然使用该方法,但是功能已经变了
            return self.__width * self.__length * self.__high
    
    
    #对于仍然在使用tell_area接口的人来说,根本无需改动自己的代码,就可以用上新功能
    >>> r1.tell_area()
    8000
  • 相关阅读:
    pyinstaller安装和使用
    django项目结构和运行项目
    安装django and 创建项目
    浅谈网络请求基础(理论篇)
    浅谈爬虫初识
    判断是否AVL平衡二叉书
    用递归方法判断两棵树是否相等
    广度优先搜索求树的深度
    堆排序
    归并排序
  • 原文地址:https://www.cnblogs.com/hexiaorui123/p/10201456.html
Copyright © 2011-2022 走看看