python - 在 super().__init__() 中访问超类的类属性

sta*_*lit 5 python inheritance class

我有一个Parent具有许多实例属性的类,并且我总是传递 adict来初始化实例。像这样:

info = {
    "name" : "Bob",
    "col" : 5,
    "line" : 10,
    "type" : "Alien"
}

p = Parent(info)
Run Code Online (Sandbox Code Playgroud)

__init__方法中,我不想this.property_name = value为每个属性编写,因为代码会很长。例如:

class Parent(object):

    def __init__(self, kwargs):
        this.name = kwargs.get("name")
        this.col = kwargs.get("col")
        this.line = kwargs.get("line")
        this.type = kwargs.get("type")
Run Code Online (Sandbox Code Playgroud)

所以我想使用一个函数来迭代dict来设置这些实例属性。这是我写的函数:

def initialize_properties(instance, names, kwargs):
    for name in names:
        setattr(instance, name, kwargs.get(name))
Run Code Online (Sandbox Code Playgroud)

看来我需要将属性名称列表存储names在某处,并且我决定将其存储为类属性,因为我希望我的类对人类友好(当有人读取类定义时,他知道该类具有哪些实例属性)。所以我改变了我的类定义如下:

class Parent(object):
    props = ("name", "col", "line", "type")

    def __init__(self, kwargs):
        initialize_properties(self, self.props, kwargs)
Run Code Online (Sandbox Code Playgroud)

当不考虑继承时,这很有效。当我子类化时会出现问题Parent

class Child(Parent):
    props = ("foo", "bar")

    def __init__(self, kwargs):
        super().__init__(kwargs)
        initialize_properties(self, self.props, kwargs)
Run Code Online (Sandbox Code Playgroud)

我希望 的 实例Child继承 superclass 中的所有实例属性Parent,以及一些特定于子类的实例属性。(这就是我们使用继承的原因,不是吗?)所以我覆盖类属性props来定义特定于子类的属性。

但这不起作用。

info = {
    "name" : "Bob",
    "col" : 5,
    "line" : 10,
    "type" : "Alien",
    "foo" : 5,
    "bar" : 10
}

c = Child(info)
Run Code Online (Sandbox Code Playgroud)

实例c只有c.foo定义c.bar和设置,而c.name没有定义。

经过一番挖掘,我发现当Parent.__init__(self, kwargs)通过函数调用时super()self传递的参数属于 class Child,因此self.props计算结果为Child.props

如果我想在 中设置实例属性Parent.props,我必须显式使用Parent.propsin Parent.__init__(self, kwargs),即:

class Parent(object):
    props = ("name", "col", "line", "type")

    def __init__(self, kwargs):
        initialize_properties(self, Parent.props, kwargs)
Run Code Online (Sandbox Code Playgroud)

这将解决问题,但我认为它不是很“干净”,因为你必须对类名进行硬编码Parent

所以我的问题是:当您调用链来初始化子类实例时,有什么方法可以检测当前类并访问其类属性吗?super().__init__()

sch*_*ggl 3

您可以实现一个props从所有超类收集 并在 中使用它的方法__init__

class Parent(object):
    props = ("name", "col", "line", "type")

    def __init__(self, **kwargs):
        def __init__(self, kwargs):
        initialize_properties(self, self.get_props(), kwargs)

    def get_props(self):
        return sum((getattr(k, 'props', ()) for k in self.__class__.mro()), ())
Run Code Online (Sandbox Code Playgroud)

现在,您可以按照您想要的方式简单地定义子类。您甚至不必重写构造函数:

class Child(Parent):
    props = ("foo", "bar")
Run Code Online (Sandbox Code Playgroud)

话虽这么说,你声称你希望你的课程对人友好。如果有人阅读您的孩子的课程,他们会很高兴阅读:

class Child(Parent):
    props = 'foo', 'bar', 'name', 'col', 'line', 'type'
Run Code Online (Sandbox Code Playgroud)

并将所有班级都props集中在一处。