首先,这个问题可能是重复的,但不知怎么的,我还没有弄清楚这些答案。假设我有:
import argparse
class Parent:
def __init__(self):
self.parser = argparse.ArgumentParser()
self.parser.add_argument("user")
# parse the argument
self.parser.parse_args()
class Child(Parent):
def __init__(self):
# here self.parser is not defined
# self.parser.add_argument("password")
super().__init__()
# here args are already parsed and
# self.parser does not include args
# self.parser.add_argument("password")
if __name__ == '__main__':
Child()
这是我想写的代码的最小工作示例(类似于命令行应用程序框架
class Parent:
def __init__(self):
# do some stuff starting stuff
# middle
# do some ending stuff
class Child(Parent):
def __init__(self):
# do something in the middle of Parent init
在我的情况下,有一个简单的局部解决方法。当Parent
可能不执行self.parser.parse_args()
,或者它会以某种方式时(现在不知道具体如何写入)检查,如果child添加了任何参数,然后将self.parser.parse_args()
留给child类。但我想,是否有可能有一个愚蠢的想法是将父级的__init__
更改为像装饰器而不是子级,并做这样的事情(事实的一部分是,init确实允许返回除None
之外的任何东西,它可能由于各种其他原因而不起作用…?)
class Child(Parent):
@super.__init__
def __init__(self):
那么,有什么想法吗?我应该选择哪条路?我这样做的动机是,我希望最终用户使用这样的框架(这意味着编写从Parent继承的应用程序),需要做尽可能少的工作(意味着将大多数事情转移到Parent中)。有没有合理的方法,如何做到这一点?
将父类中的"中间"部分移到单独的方法中。然后,您可以在子级中覆盖仅该方法:
class Parent:
def __init__(self):
self._construct_parser()
# parse the argument
self.parser.parse_args()
def _construct_parser(self):
self.parser = argparse.ArgumentParser()
self.parser.add_argument("user")
class Child(Parent):
def _construct_parser(self):
super()._construct_parser()
# add on to self.parser
这基本上是另一个问题的至少一个答案告诉你要做的;将父__init__
中的各个部分拆分为单独的方法,每个方法都可以单独重写。
如果您正在将其作为一个框架,那么添加特定的钩子也是一种选择。父类定义了在特定点调用的空方法,子类可以实现这些空方法来参与特定步骤。这里将是ArgumentParser
类的构造位置,并且可以添加一个子类:
class Parent:
def __init__(self):
self._construct_parser()
# parse the argument
self.parser.parse_args()
def _construct_parser(self):
self.parser = argparse.ArgumentParser()
self.parser.add_argument("user")
self.update_parser(self.parser)
# hook method
def update_parser(self, parser):
pass
class Child(Parent):
def update_parser(self, parser):
# add to parser
现在,子类甚至不再需要使用super()
;它得到了它所需要的一切,由框架预先消化,以更新解析器。