Абстрактный класс + mixin + множественное наследование в python

Итак, я думаю, что код, вероятно, объясняет, что я пытаюсь сделать лучше, чем могу, словами:

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 удовлетворять требованиям класса abstract/interface. Что мне не хватает?

Ответы

Ответ 1

Разве наследование не должно быть наоборот? В MRO foo в настоящее время наступает до bar_for_foo_mixin, а затем справедливо жалуется. С class myfoo(bar_for_foo_mixin, foo) он должен работать.

И я не уверен, что ваш дизайн класса - это правильный способ сделать это. Поскольку вы используете mixin для реализации bar, лучше не выводить из foo и просто регистрировать его с помощью класса "foo" (т.е. foo.register(myfoo)). Но это только мое чувство кишки.

Для полноты, вот документация для ABC.

Ответ 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()