python python中的抽象类+mixin+多重继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/825945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 20:55:29  来源:igfitidea点击:

Abstract class + mixin + multiple inheritance in python

pythonabstract-classmultiple-inheritancemixins

提问by mluebke

So, I think the code probably explains what I'm trying to do better than I can in words, so here goes:

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

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()

The result:

结果:

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

I'm trying to get the mixin class to satisfy the requirements of the abstract/interface class. What am I missing?

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

采纳答案by nikow

Shouldn't the inheritance be the other way round? In the MRO foocurrently comes before bar_for_foo_mixin, and then rightfully complains. With class myfoo(bar_for_foo_mixin, foo)it should work.

继承不应该是相反的吗?在 MROfoo目前出现之前bar_for_foo_mixin,然后理所当然地抱怨。有了class myfoo(bar_for_foo_mixin, foo)它应该工作。

And I am not sure if your class design is the right way to do it. Since you use a mixin for implementing barit might be better not to derive from foo and just register it with the 'foo' class (i.e. foo.register(myfoo)). But this is just my gut feeling.

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

For completeness, here is the documentation for ABCs.

为了完整起见,这里是ABCs文档

回答by Lars

i think (tested in similar case) that reversing the baseclasses works:

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

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

so in the mro() it would find a concrete version of bar() before it finds the abstract one. No idea if this is actually what happens in the background though.

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

Cheers, Lars

干杯,拉斯

PS: the code that worked in python 2.7 (python 3 has a different way to set metaclasses) was:

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()