调用 super().__init__() 时会给出错误的方法

Calling super().__init__() gives the wrong method when it is overridden

我有一个基础 class 和一个子 class。在基础 class 中,我有一个在 __init__ 中调用的实例方法。在 sub class 中我已经覆盖了这个方法。 sub class 中的 super() 调用不是调用原始基方法而是重写的 sub class 方法。为什么?

class BaseClass:
    def __init__(self, value):

        self.value = value
        self.transformed_value = self.create_value(value)

    def create_value(self, value):

        print("base")
        return value + 1

class SubClass(BaseClass):
    def __init__(self, value):

        super().__init__(value)

    def create_value(self, value):
        print("sub")
        return value + 2

s = SubClass(3)

我希望打印输出为 "base",但实际输出为 "sub"。如何修改代码以获取 "base" 而无需在 BaseClass__init__ 中显式调用 BaseClass.create_value(self, value)

Python 是动态输入的。这意味着当你写

def __init__(self, value):
    self.value = value
    self.transformed_value = self.create_value(value)

在评估 self.create_value 时该方法属于哪个 class 并不重要:它只重要 type of self是调用方法的时候。

当您调用 SubClass(3) 时,您最终会调用 SubClass.__init__,它会立即调用 BaseClass.__init__,并使用 SubClass 类型的参数。由于 SubClass.create_value 已定义,因此 self.create_value 解析为。

如果出于某种原因,您坚持 BaseClass.__init__ 在其 self 参数上调用 BaseClass.create_value,您必须使用 BaseClass.create_value(self, value) 明确地这样做。然而,这很少是一个好主意。如果 self 的类型想要调用它覆盖的方法,那么 有责任这样做,通过使用 super 本身:

def create_value(self, value):
    rv = super().create_value()
    print("sub")
    return value + 2  # Or perhaps do something with rv first?

进一步补充@chepner 的优雅答案,如果你想让父 class 调用它自己的方法,你可以修改父 class 如下:

class BaseClass:

    def __init__(self, value):
        self.value = value
        self.transformed_value = self.base_create_value(value)     # use the renamed reference

    def create_value(self, value):
        print("base")
        return value + 1

    base_create_value = create_value   # create a local reference to the method

在上面的 BaseClass 中,我们创建了一个对父方法的简单引用,并在它自己的 __init__ 方法中使用了相同的方法。通过这样做,我们可以继续使用这个引用对象,即使基础 class' 方法被覆盖并且当它被子实例调用时。