zoukankan      html  css  js  c++  java
  • python继承实现原理封装property

    ---恢复内容开始---

    在Python中继承顺序有两种:深度优先和广度优先

    没有共同父类的继承:

    class E:
        def test(self):
            print('from E')
    class A(E):  #步骤4 A(E) #from E
        # def test(self):
        #     print('from A') #步骤2 from B
        pass
    class B:
        # def test(self):
        #     print('from B')  #步骤3 from C
        pass
    class C:
        # def test(self):
        #     print('from C')
        pass
    class D(A,B,C):
        # def test(self):
        #     print('from D')  #步骤1 from A
        pass
    t=D() #实例化对象t
    t.test()

    这种类型的继承新式类和经典类的顺序是一样的都是深度优先:D--->A--->E--->B--->C

    共同父类的继承

    class D(object):
        def test(self):
            print('from D')
        # pass
    class C(D):
        def test(self):
            print('from C')
        # pass
    class B(C):
        def test(self):
            print('from B')
        # pass
    class F(D):
        def test(self):
            print('from F')
        # pass
    class E(F):
        def test(self):
            print('from E')
        # pass
    class H(D):
        def test(self):
            print('from H')
        # pass
    class G(H):
        def test(self):
            print('from G')
        # pass
    
    class A(B,E,G):
        def test(self):
            print('from A')
        # pass
    
    obj=A()
    obj.test()
    print(A.mro())
    #经典类不继承object
    class D:
        def test(self):
            print('from D')
        # pass
    class C(D):
        def test(self):
            print('from C')
        # pass
    class B(C):
        def test(self):
            print('from B')
        # pass
    class F(D):
        def test(self):
            print('from F')
        # pass
    class E(F):
        def test(self):
            print('from E')
        # pass
    class H(D):
        def test(self):
            print('from H')
        # pass
    class G(H):
        def test(self):
            print('from G')
        # pass
    
    class A(B,E,G):
        def test(self):
            print('from A')
        # pass
    
    obj=A()
    obj.test()

    在这种类型继承下新式类和经典类的顺序不同。

    新式类采取广度优先:A--->B--->C--->E--->F--->G--->H--->D--->object

    经典类(python2中才有经典类的概念,python3中都是新式类)使用的是深度优先的方式A--->B--->C--->D--->E--->F--->G

    mro():

    只有新式类才具有的方法

    print(A.mro())
    执行结果
    [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class '__main__.G'>, 
    <class '__main__.H'>, <class '__main__.D'>, <class 'object'>]

    可以通过该方法来查看父类的继承顺序

    子类调用父类的两种方法:

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
        def foo(self):
            print('from parent')
    
    class Teacher(People):
        def __init__(self,name,age,sex,level,salary):
            # People.__init__(self,name,age,sex)  #方法一
            super().__init__(name,age,sex) #super(Teacher,self).__init__(name,age,sex) #方法二
            self.level=level
            self.salary=salary
        def foo(self):
            super().foo()
            print('from child')

    封装

    封装是一种隐藏的方式,包括数据封装和功能封装,即类里的数据属性和功能属性,隐藏数据和功能是为了限制直接调用,通过人为的添加调用接口进行数据和功能的调用

    封装的变形操作只在类的定义阶段或者对象的实例化阶段

    封装的主要原因:

    1.保护隐私

    2.隔离复杂度,提供简单的接口

    class Teacher:
        def __init__(self,name,salary):
            self.name=name
            self.__salary=salary
        def foo(self):
            print('balabala',self.__salary)
    
    t=Teacher('xiaolan',5000)
    print(t.salary)
    执行结果
    AttributeError: 'Teacher' object has no attribute 'salary'
    print(t.__dict__)
    print(t._Teacher__salary)
    t.foo()
    执行结果
    {'name': 'xiaolan', '_Teacher__salary': 5000}
    5000
    balabala 5000
    class A:
        def foo(self):
            print('from A.foo')
            self.__bar()
        def __bar(self):
            print('from A.bar')
    
    class B(A):
        def bar(self):
            print('from B.bar')
        pass
    b=B()
    b.foo()
    执行结果
    from A.foo
    from A.bar

    在封装后对象的数据属性和函数属性以‘_类名__属性’名的形式保存

    class Foo:
        def __func(self): #_Foo__func
            print('from Foo')
    
    class Bar(Foo):
        def __func(self): #_Bar__func
            print('from Bar')
    b=Bar()
    b._Foo__func()
    b._Bar__func()

    在父类和子类有相同的属性时不会担心子类的属性将父类的属性覆盖调用

    class People:
        def __init__(self,name,age,sex,height,weight):
            self.__name=name
            self.__age=age
            self.__sex=sex
            self.__height=height
            self.__weight=weight
    #name、age、sex、height、weight都是经过封装后保存,所以外部调用的时候没办法直接调用
        def tell_name(self):
            print(self.__name)
    #通过手动创建接口的方式返回name的内容,屏蔽了直接调用
        def set_name(self,val):
            if not isinstance(val,str):
                raise TypeError('type must be str')
            self.__name=val
    #通过手动创建修改接口修改name的属性值,屏蔽了直接调用
        def tell_info(self):
            print('''
            ---------%s info
            name:%s
            age:%s
            sex:%s
            height:%s
            weight:%s
            ''' %(self.__name,
                  self.__name,
                  self.__age,
                  self.__sex,
                  self.__height,
                  self.__weight))
    #通过手动创建接口,展示所有的信息

    property:封装的特性之一

    property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值,可以讲函数功能的执行伪装为数据属性

    property的构造方法中有个四个参数

    • 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
    • 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
    • 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
    • 第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
    class People:
        def __init__(self,name,age,sex,height,weight):
            self.__name=name
            self.__age=age
            self.__sex=sex
            self.__height=height
            self.__weight=weight
    
        @property    #bmi=property(bmi),是一个内置函数,本质就是个装饰器
        def bmi(self):
            res=self.__weight / (self.__height ** 2)
            return res
    xiaobai=People('xiaobai',22,'male',1.80,67)
    print(xiaobai.bmi)
    执行结果
    20.679012345679013
    class People:
        def __init__(self,name,age,sex,height,weight,permission=False):
            self.__name=name
            self.__age=age
            self.__sex=sex
            self.__height=height
            self.__weight=weight
            self.permission=permission
        @property
        def name(self):
            return self.__name
        @name.setter            #支持obj.name='NAME'的方式执行
        def name(self,val):
            if not isinstance(val,str):
                raise  TypeError('must be str')
            self.__name=val
        @name.deleter        #支持del删除操作
        def name(self):
            if not self.permission:
                raise PermissionError('不让删')
            del self.__name
    xiaobai=People('xiaobai',22,'male',1.80,67)
    print(xiaobai.name)
    xiaobai.name='xiaobai Lyn'
    print(xiaobai.__dict__)
    xiaobai.permission=True
    del xiaobai.name
    print(xiaobai.__dict__)
    执行结果
    xiaobai
    {'_People__name': 'xiaobai Lyn', '_People__age': 22, '_People__sex': 'male', '_People__height': 1.8, '_People__weight': 67, 'permission': False}
    {'_People__age': 22, '_People__sex': 'male', '_People__height': 1.8, '_People__weight': 67, 'permission': True}
    class Foo:
    
        def get_bar(self):
            return 'xiaobai'
    
        # *必须两个参数
        def set_bar(self, value): 
            return 'set value' + value
    
        def del_bar(self):
            return 'xiaobai'
    
        BAR = property(get_bar, set_bar, del_bar, 'description...')
    
    obj = Foo()
    
    obj.BAR              # 自动调用第一个参数中定义的方法:get_bar
    obj.BAR = "youzi"     # 自动调用第二个参数中定义的方法:set_bar方法,并将“youzi”当作参数传入
    del Foo.BAR          # 自动调用第三个参数中定义的方法:del_bar方法
    obj.BAE.__doc__      # 自动获取第四个参数中设置的值:description...
  • 相关阅读:
    matlab代码学习_2018728
    理解面向对象过程中创造一个对象的步骤
    html字符及空格占位问题
    div中img(及文字等inline元素和block元素)的自动换行
    css布局居中
    css3前缀解决方案
    自己写一个树形导航菜单
    《JavaScript核心概念及实践》 读书笔记
    css常用属性
    windows下有个目录名称中间有空格 java读目录空格变成%20 处理方法
  • 原文地址:https://www.cnblogs.com/c491873412/p/7127244.html
Copyright © 2011-2022 走看看