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...
原文地址:https://www.cnblogs.com/c491873412/p/7127244.html