Python 面向对象 三大特性 继承

概念

一个类拥有另外一个类的资源的方式之一
并不是资源的复制,变成双份资源,而是资源的使用权
资源指非私有的属性和方法

分类

单继承

class Animal:
    pass

class Dog(Animal):
    pass

多继承

class Animal:
    pass

class xxx:
    pass

class Dog(Animal, xxx):
    pass

查看父类:

class Animal:
    pass

class xxx:
    pass

class Dog(Animal, xxx):
    pass

print(Dog.__bases__)

(<class ‘main.Animal’>, <class ‘main.xxx’>)

type 与 object 区别

class Animal:
    pass

class xxx:
    pass

class Dog(Animal, xxx):
    pass

print(Dog.__bases__)
print(Animal.__bases__)

print(int.__bases__)
print(float.__bases__)
print(bool.__bases__)

d = Dog()

print(d.__class__)
print(Dog.__class__)
print(type.__class__)

(<class ‘main.Animal’>, <class ‘main.xxx’>)
(<class ‘object’>,)
(<class ‘object’>,)
(<class ‘object’>,)
(<class ‘int’>,)
<class ‘main.Dog’>
<class ‘type’>
<class ‘type’>

继承对资源的影响

在python中,继承是指资源的使用权。所以,测试某个资源能否被继承,其实就是测试在子类中能不能访问到父类中的这个资源
除了私有的属性和私有的方法,其他的基本都能继承。

继承内容:

  • 公有属性、方法
  • 受保护的属性、方法
  • 内置方法
class Animal:
    # 属性 和 方法
    # 设置不同权限的属性和方法,继承当中,进行测试
    # 在子类当中,能否访问到这些资源
    a = 1 # 公有的
    _b = 2 # 受保护的
    __c = 3 # 私有的
    
    def t1(self):
        print('t1')
    
    def _t2(self):
        print('t2')
    
    def __t3(self):
        print('t3')
    
    def __init__(self):
        print('init, Animal')


class Person(Animal):
    def test(self):
        print(self.a)
        print(self._b)
        # print(self.__c)

        self.t1()
        self._t2()
        # self.__t3()
        self.__init__()

p = Person()
p.test()

Animal.a = 666
p.test()

init, Animal
1
2
t1
t2
init, Animal
666
2
t1
t2
init, Animal

class B():
    age = 10

class A(B):
    pass

print(A.age)
A.age = 9

print(B.age)
print(A.__dict__)
print(B.__dict__)

10
10
{‘module’: ‘main’, ‘doc’: None, ‘age’: 9}
{‘module’: ‘main’, ‘age’: 10, ‘dict’: <attribute ‘dict’ of ‘B’ objects>, ‘weakref’: <attribute ‘weakref’ of ‘B’ objects>, ‘doc’: None}

继承的几种形态

  • 单继承链
  • 无重叠的多继承链
  • 有重叠的多继承链

单继承:遵循从下到上的原则,自己身上没有这个资源,就到父类里面去找。
无重叠的多继承链:遵循单调原则,按照继承的先后顺序,优先调用左侧的继承链
有重叠的多继承链:遵循重下到上的原则
继承的几种状态

概念补充

MRO: Method Resolution Order, 方法解析顺序

深度优先

沿着一个继承链,尽可能往深处查找
具体算法步骤:

  1. 把根节点压入栈中
  2. 每次从栈中弹出一个元素,搜索所有在它下一级的元素,把这些元素压入栈中
  3. 重复第2个步骤到结束为止

广度优先

沿着继承链,尽可能往宽了去找。
具体算法步骤:

  1. 把根节点放到队列的末尾
  2. 每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把他们放到队列的末尾,发现已经被处理则略过。
  3. 重复上面步骤

C3 算法

两个公式:
L(object) = [object]
L(子类(父类1, 父类2)) = [子类] + merge(L(父类1), L(父类2), [父类1, 父类2])

+ 代表合并列表

merge 算法:

  1. 第一个列表的第一个元素,是后续列表的第一个元素,或者,后续列表中没有再次出现,则将这个元素合并到最终的解析列表中,并从当前的操作的所有列表中删除。
  2. 如果不符合,则跳过此元素,查找下一个列表的第一个元素,重复1的判断规则。
  3. 如果最终无法把所有元素归并到解析列表,则报错

类似拓扑排序,但并不是

python 2.2之前

仅存在经典类,MRO原则为深度优先(从左往右),问题为有重叠的多继承,违背重写可用原则

python2.2

产生了新式类,MRO原则,经典类为深度优先(从左往右)。新式类为在深度优先(从左往右)的算法基础上,优化了一部分,如果产生重复元素,会保留最后一个,并且更尊重基类出现的先后顺序。注意,并不是广度优先算法

问题:

  1. 无法检测出有问题的继承
  2. 有可能还会违背局部优先的原则

python2.3 -2.7

新式类经典类并存
MRO原则:经典类为深度优先()从左到右。新式类为C3原则。

python 3.x

只有新式类
MRO原则:C3算法

查看继承方式

  1. inspect.getmro(A)
  2. A.mro()
  3. A.__mro__
import inspect
class C():
    age = 'c'

class B(C):
    age = 'b'

class A(B):
    age = 'a'

print(inspect.getmro(A))
print(A.mro())
print(A.__mro__)

(<class ‘main.A’>, <class ‘main.B’>, <class ‘main.C’>, <class ‘object’>)
[<class ‘main.A’>, <class ‘main.B’>, <class ‘main.C’>, <class ‘object’>]
(<class ‘main.A’>, <class ‘main.B’>, <class ‘main.C’>, <class ‘object’>)

资源的覆盖

属性的覆盖
方法的重写

import inspect

class D(object):
    age = 'd'

class C(D):
    age = 'c'

    def test(self):
        print('c')

class B(D):
    age = 'b'

    def test(self):
        print('b')

class A(B, C):
    pass

print(A.mro())
print(A.age)

print(A().test())

[<class ‘main.A’>, <class ‘main.B’>, <class ‘main.C’>, <class ‘main.D’>, <class ‘object’>]
b
b
None

资源的累加

在一个类的基础之上,增加一些额外的资源(属性和方法)
子类相比于父类,对一些自己特有的资源
在被覆盖的方法之上,新增内容


class B():
    a = 1
    def __init__(self):
        self.b = 2

    def t1(self):
        print("t1")
    
    @classmethod
    def t2(cls):
        print("t2")
    
    @staticmethod
    def t3():
        print("t3")

class A(B):
    pass

a_obj = A()

print(A.a)
print(a_obj.b)

a_obj.t1()
A.t2()
A.t3()

1
2
t1
t2
t3

方案1:通过类名调用父类方法


class B():
    a = 1
    def __init__(self):
        self.b = 2

    def t1(self):
        print("t1")
    
    @classmethod
    def t2(cls):
        print("t2")
    
    @staticmethod
    def t3():
        print("t3")

class A(B):
    def __init__(self):
        B.__init__(self)
        self.xxx = "124"

a_obj = A()
print(a_obj.__dict__)

{‘b’: 2, ‘xxx’: ‘124’}

产生的问题:


class D(object):
    def __init__(self):
        print("d")

class B(D):
    def __init__(self):
        D.__init__(self)
        print("b")
        
class C(D):
    def __init__(self):
        D.__init__(self)
        print("c")

class A(B, C):
    def __init__(self):
        B.__init__(self)
        C.__init__(self)
        print("a")

A()

d
b
d
c
a

方案2:super

在低优先级类的方法中,通过super调用高优先级类的方法
super是一个类,只有在新式类中有效
起着代理的作用,帮我们完成以下任务,沿着MRO链条,找到下一级节点,去调用对应的方法
语法原理:
super(参数1[, 参数2])

工作原理:

def super(cls, inst):
    mro = inst.__class.mro()
    return mro[mro.index(cls) + 1]

沿着谁的MRO链条?参数2
找谁的下一个节点?参数1
如何应对类方法,静态方法以及实例方法的传参问题?使用参数2进行调用


class B():
    def __init__(self):
        self.b = 2
        self.xxx = "xxx"

    def t1(self):
        print("t1")
    
    @classmethod
    def t2(cls):
        print("t2")
    
    @staticmethod
    def t3():
        print("t3")


class A(B):
    def __init__(self):
        super().__init__()
        self.e = "666"

    def tt1(self):
        print("tt1")
    
    @classmethod
    def tt2(cls):
        super(A, A).t2()
        print("tt2")
    
    @staticmethod
    def tt3():
        print("tt3")
a = A()
print(a.__dict__)

A.tt2()

{‘b’: 2, ‘xxx’: ‘xxx’, ‘e’: ‘666’}
t2
tt2

class D(object):
    def __init__(self):
        print("d")

class B(D):
    def __init__(self):
        super().__init__()
        print("b")
        
class C(D):
    def __init__(self):
        super().__init__()
        print("c")

class A(B, C):
    def __init__(self):
        super().__init__()
        print("a")

A()

d
c
b
a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值