【问题标题】:Understanding multiple inheritence and super based on some code from David Beazly根据 David Beazley 的一些代码理解多重继承和超级
【发布时间】:2017-07-26 21:05:48
【问题描述】:

我看过 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

我的问题是:

  1. 为什么需要定义带有方法检查的基类 Contract 才能完成这项工作?

  2. 我对 super 的作用有一个基本的了解。我知道它可以让我们避免显式调用基类并以某种方式处理多重继承。但是在这个例子中它到底做了什么?

【问题讨论】:

  • @NickT:我知道这个线程并且我确实阅读了它,但它并没有帮助我理解这个问题
  • 我认为这个想法是,在 MRO 的某个地方应该/必须有一个方法,以便您将它放在基类中 - 即使它不做任何事情或只是引发 NotImplemented 异常。
  • 看看Python's super() considered super!的实用建议部分
  • @wwii:我想我确实表达得不清楚。你能看看我对 Artyer 回答的评论吗?

标签: python multiple-inheritance diamond-problem


【解决方案1】:

让我们像调试器一样逐行浏览它。

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,如@987654333 @ 将无法找到它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-02
    • 2016-09-03
    • 2012-07-06
    • 2020-02-29
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多