在子类中启动超类对象

initiate superclass object in subclass

有人可以向我解释一下 child_2 class 中的 super() 是怎么回事吗?我发现 super() 启动是在 child_2 而不是 child_1 中获取 convert_id() 函数,这有点违反直觉。我想通过调用super(),它假设使用class_1中的函数来启动对象。

from abc import ABC, abstractmethod

class base(ABC):
    @abstractmethod
    def convert_id(self, id):
        pass

class child_1(base, ABC):
    def __init__(self, id):
        self.new_id = self.convert_id(id)

    def convert_id(self, id):
        return id

class child_2(child_1):
    def __init__(self, id):
        self.id = id
        super().__init__(id=self.id)

    def convert_id(self, id):
        return id+1

test = child_2(0)
print(test.new_id)
1

这是在具有继承的面向对象编程中正常的、预期的和基本的行为方式。

这个想法是,您的专用 classes(继承的 classes)可以专门化特定方法。一般模式是 superclass 中的一个方法可以协调调用各种其他方法来为相关实例执行特定任务——并且,如果一个专门的 subclass 关心改进其中一个通过覆盖它的方法,即调用的方法。

在运行时术语中,child_1.__init__ 收到的 selfchild_2 的一个实例(它也恰好是 child_1 的一个实例) - 但在接收到的对象中调用的方法将从 child_2 解析。 如果您将 child_1.__init__ 中的“self”视为 child_1 的实例,那只是“违反直觉”。这种“铸造”永远不会发生,在 Python.

中也不是自然可行的

现在,如果您的代码中有一个需要此行为的模式:child_1 中的 __init__ 仅调用 child_1 中定义的方法,而不是重载subclass 中的方法,通过“name mangling”机制可行:如果方法或属性以两个下划线 (__) 开头,编译器将烘焙 class 名称进入该方法或属性名称,以某种方式它不会被意外覆盖(而 __ 的提示向程序员明确表明它不应该被覆盖)。在 Python 以外的其他语言中,此行为是通过使用“私有”方法实现的:一种子 classes 本身无法访问的方法(与“受保护”不同)。

及时:此行为与您继承自 abc.ABC 或它使用的自定义元 class 的事实无关 - 这就是语言的工作方式。

换句话说,如果您调用方法 __convert_id 而不是 convert_id,您预期的行为将会发生。但请记住,这 不是 继承的自然行为,它只是一种比简单地允许方法被覆盖更少用处的可能方式。