【问题标题】:Abstract class + mixin + multiple inheritance in pythonpython中的抽象类+mixin+多重继承
【发布时间】:2010-10-23 23:32:07
【问题描述】:

所以,我认为代码可能比文字更好地解释了我想要做的事情,所以这里是:

import abc

class foo(object):
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    def bar(self):
        pass


class bar_for_foo_mixin(object):
    def bar(self):
        print "This should satisfy the abstract method requirement"


class myfoo(foo, bar_for_foo_mixin):
    def __init__(self):
        print "myfoo __init__ called"
        self.bar()

obj = myfoo()

结果:

TypeError: Can't instantiate abstract class myfoo with abstract methods bar

我试图让 mixin 类满足抽象/接口类的要求。我错过了什么?

【问题讨论】:

    标签: python abstract-class multiple-inheritance mixins


    【解决方案1】:

    继承不应该反过来吗?在 MRO 中 foo 当前排在 bar_for_foo_mixin 之前,然后理所当然地抱怨。使用class myfoo(bar_for_foo_mixin, foo) 应该可以工作。

    我不确定你的班级设计是否正确。由于您使用 mixin 来实现 bar,因此最好不要从 foo 派生而只需将其注册到 'foo' 类(即foo.register(myfoo))。但这只是我的直觉。

    为了完整起见,这里是documentation for ABCs

    【讨论】:

    • 好的调用,改变继承顺序就可以了。附:代码被简化以说明一点。我的现实世界场景要复杂得多,有很多潜在的 mixin 和 myfoo。
    【解决方案2】:

    我认为(在类似情况下测试)反转基类是有效的:

    class myfoo(bar_for_foo_mixin, foo):
        def __init__(self):
            print "myfoo __init__ called"
            self.bar()
    

    所以在 mro() 中它会在找到抽象版本之前找到 bar() 的具体版本。不知道这是否真的是在后台发生的。

    干杯,拉斯

    PS:在 python 2.7 中工作的代码(python 3 有不同的方式来设置元类)是:

    class A(object):
        __metaclass__ = abc.ABCMeta
    
        @abc.abstractmethod
        def do(self):
            pass
    
    class B(object):
        def do(self):
            print "do"
    
    class C(B, A):
        pass
    
    c = C()
    

    【讨论】:

    • 感谢您的回答。在 py27 中,您的有效代码确实强制在 C 类中存在 do()。但是,在 py3 中(我只在 py35 中测试过),情况不再如此。在B 类中,您可以将主体替换为pass,然后将愉快地创建实例c。你知道为什么会这样吗?
    • @cjrh:你是指B的身体还是B.do的身体?如果是第一个,那就太奇怪了,因为它有点违背 abc 的目的 ..
    • 只需在“PS:有效的代码是”下尝试您的代码,但将B 更改为class B(object): pass。您将看到实例c 已成功创建。我在 Python 3.6 上试过,结果一样。
    • 好的,我明白了。 __metaclass__ 不再是您在 Python 3 中声明元类的方式。相反,您必须在类 args 中指定元类,例如 class A(metaclass=abc.ABCMeta): <etc>。然后它就像 Python 2 一样工作。
    • 检查,添加到答案
    猜你喜欢
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多