关于python:基于David Beazley的一些代码了解多重继承和超级

Understanding multiple inheritence and super based on some code from David Beazly

我看了大卫比兹利的一个屏幕剪辑,他使用多个或者更具体的钻石继承来实现类型检查。我认为他的方法看起来很酷,但也让我困惑,我根本不知道它是如何工作的。下面是我要说的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Contract:
    @classmethod
    def check(cls, value):
        pass


class Integer(Contract):
    @classmethod
    def check(cls, value):
        assert isinstance(value, int), 'Expected int'
        super().check(value)


class Positive(Contract):
    @classmethod
    def check(cls, value):
        assert value > 0, 'Must be > 0'
        super().check(value)


class PositiveInteger(Positive, Integer):
    pass

它的作用是:

1
2
3
4
5
6
7
8
9
10
11
>>> PositiveInteger.check(-3)
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
  File"<stdin>", line 4, in check
AssertionError: Must be > 0
>>> PositiveInteger.check(4.88)
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
  File"<stdin>", line 5, in check
  File"<stdin>", line 4, in check
AssertionError: Expected int

我的问题是:

  • 为什么需要使用带有方法检查的基类契约的定义来实现这一点?

  • 我对Super的工作有一个基本的了解。我知道它让我们避免显式地调用基类,并且以某种方式处理多重继承。但在这个例子中它究竟做了什么呢?


  • 让我们像调试程序一样一行一行地检查它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    PositiveInteger.check(x)

    # Method resolution order:
    # PositiveInteger, Positive, Integer, Contract (from Positive), Contract (from Integer)

    # Look through MRO for .check() method. Found in Positive.

    assert x > 0
    super().check(value)

    # super() checks for next .check() method in MRO. Found in Integer

    assert isinstance(x, int)
    super().check(value)

    # super() checks for next .check() method in MRO. Found in Contract

    pass

    为了方便地找到方法的分辨率顺序,使用inspect.getmro()

    如果您已经显式地使用了基类,那么在Positive之后,基类就是Contract,所以不会调用Integer

    你需要在Contract中把.check()定义为当你调用最后一个super()时,如果Contract没有.check()方法,它就会提出一个AttributeError,因为super()找不到它。