首页 > 解决方案 > 如何动态调用每个父级的__init__

问题描述

我已经阅读了关于 SO 与我的问题最相似的问题,这是关于单父继承的,唯一提到多父继承的答案建议读者使用调用该方法 ( )的静态形式,正如所指出的那样评论中的内容并不总是干净的。SomeSuperClass.someMethod(self, args)

我正在寻求一种动态someMethod调用特定超类的特定方法的方法,例如:SomeSuperClass

class SomeSuperClass():
    def someMethod(self, args):
        print("Hello,", end="")

class Subclass(SomeSuperClass, OtherSuperClass):
    def someMethod(self, args):

        # static calling (I do not want this solution)
        SomeSuperClass.someMethod(self, args)

        # dynamic calling (I want this one)
        (my SomeSuperClass-ness).someMethod(args)

        print("world!")

这是我实际测试并希望工作的代码:

class Something():
    def __init__(self, a, b) -> None:
        self.sum = a+b


class SomethingElse():
    def __init__(self, c, d) -> None:
        self.product = c * d


class Both(Something, SomethingElse):
    def __init__(self, a, b) -> None:

        # sadly this does not work
        super(Something, self).__init__(a, b)
        super(SomethingElse, self).__init__(a, b)

        # the following works, but is static and does not use super
        # Something.__init__(self, a, b)
        # SomethingElse.__init__(self, a, b)

b = Both(10, 20)

print(b.sum, b.product)

运行此代码会导致以下错误:

TypeError: object.__init__() takes exactly one argument (the instance to initialize)

显然它正在尝试调用__init__of object。在这种情况下,如何super正确使用它才能真正调用适当__init__的 s?

标签: python-3.xoopinheritancesuper

解决方案


该函数将在您指定的之后super()委托给父级 - 请参见此处,特别是以下注释:

对象或类型确定要搜索的方法解析顺序。搜索从紧随其后的类开始type

所以要正确使用它,你应该使用super()来指代Something,和super(Something, self)指代SomethingElse; 您可以通过阅读类的__mro__属性来查看顺序Both

class Something():
    pass

class SomethingElse():
    pass

class Both(Something, SomethingElse):
    pass

print(Both.__mro__)

这会告诉你顺序:

(<class '__main__.Both'>, <class '__main__.Something'>, <class '__main__.SomethingElse'>, <class 'object'>)

并解释为什么你最后object.__init__打电话给super(...).__init__(...).


推荐阅读