基于 David Beazley 的一些代码理解多重继承和超类
Understanding multiple inheritence and super based on some code from David Beazly
我看过 David Beazly 的 screencast,他在其中使用多个或更具体的菱形继承来实现类型检查。我认为他的方法看起来很酷,但它也让我感到困惑,我根本无法弄清楚它是如何工作的。这是我正在谈论的代码:
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
它正在运行:
>>> 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
我的问题是:
为什么要定义一个基础 class 合同并进行方法检查才能使这项工作正常进行?
我对super的作用有了基本的了解。我知道它让我们避免显式调用基 class 并以某种方式处理多重继承。但是在这个例子中它到底做了什么?
让我们像调试器一样逐行检查它。
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
之后显式使用基数 class,则基数 class 是 Contract
,因此永远不会调用 Integer
。
你需要在Contract
中定义.check()
作为你调用最后一个super()
的时候,如果Contract
没有.check()
方法,它会引发 AttributeError
,因为 super()
无法找到它。
我看过 David Beazly 的 screencast,他在其中使用多个或更具体的菱形继承来实现类型检查。我认为他的方法看起来很酷,但它也让我感到困惑,我根本无法弄清楚它是如何工作的。这是我正在谈论的代码:
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
它正在运行:
>>> 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
我的问题是:
为什么要定义一个基础 class 合同并进行方法检查才能使这项工作正常进行?
我对super的作用有了基本的了解。我知道它让我们避免显式调用基 class 并以某种方式处理多重继承。但是在这个例子中它到底做了什么?
让我们像调试器一样逐行检查它。
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
之后显式使用基数 class,则基数 class 是 Contract
,因此永远不会调用 Integer
。
你需要在Contract
中定义.check()
作为你调用最后一个super()
的时候,如果Contract
没有.check()
方法,它会引发 AttributeError
,因为 super()
无法找到它。