从Python中的公共函数中提取mixin

从Python中的公共函数中提取mixin,python,oop,inheritance,mixins,Python,Oop,Inheritance,Mixins,考虑两个类,每个类都有一个现有的共享函数,但有单独的继承路径: class ClazzA(SuperClazzX): def foo(self): return goo(super(SuperClazzX, self).foo()) class ClazzB(SuperClazzY): def foo(self): return goo(super(SuperClazzY, self).foo()) foo显然是一个可以提取到mixin中的常见

考虑两个类,每个类都有一个现有的共享函数,但有单独的继承路径:

class ClazzA(SuperClazzX):
    def foo(self):
        return goo(super(SuperClazzX, self).foo())

class ClazzB(SuperClazzY):
    def foo(self):
        return goo(super(SuperClazzY, self).foo())
foo
显然是一个可以提取到mixin中的常见函数,正确的方法是什么,这样即使要调用不同的super
foo
,功能仍然保持不变

编辑:我删除了另一个mixin,它让人感到困惑和不相关。

编辑:更简单的代码

Mixin可以访问(未来)子类的其他基,这里
C::Mixin::foo
可以访问
C
的其他基,即
C::base::foo

它的作用是:

  • self
    C
    的实例,它是
    \uuumro\uuuuu
    是(Mixin,Base)
  • 当Mixin调用
    super(Mixin,self)
    时,生成的对象将保留Base(Base,)
  • 解析
    .foo
    属性时,此对象将在Base中找到它
  • 因此,
    Base.foo
    被原始的
    self
如果您希望对实施进行自定义控制,您可以访问自己的基础,例如:

class Foo(...):
    def foo(self):
        print self.__class__.__bases__
您的mixin可能看起来像这样,超级手动方式:

class Mixin(object):
    def foo(self):
        assert self.__class__ is not Mixin  # no point calling directly
        # find the other base
        other = [b for b in self.__class__.__bases__ if b is not Mixin]
        # what to do if there's more than 1 real base?
        # pick base explicitly
        base = other[1]
        # call it, 
        return something(base.foo(self, some_args))

是否有其他类继承了
CommonMixin
,它能进入其中吗?不,
CommonMixin
是无关的。你是说重构现有代码还是从头开始设计?@BurhanKhalid这是现有代码,但它真的重要吗?我想是的;也许福在不同的班级做不同的事情?现在来看,我认为装饰师可能是一个更好的方法。这如何回答这个问题?@qarma希望它澄清:)这似乎是错误的。Python不应该通过显式调用
self来正确解析
super()。它返回一个神奇的对象,当您尝试在中查找
.foo
属性时,它将在链中找到实际定义
.foo
的下一个类。
class Mixin(object):
    def foo(self):
        assert self.__class__ is not Mixin  # no point calling directly
        # find the other base
        other = [b for b in self.__class__.__bases__ if b is not Mixin]
        # what to do if there's more than 1 real base?
        # pick base explicitly
        base = other[1]
        # call it, 
        return something(base.foo(self, some_args))