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__()
您可以实现一个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集中在一处。
| 归档时间: |
|
| 查看次数: |
3681 次 |
| 最近记录: |