如何使用父方法装饰(包装)子方法

时间:2016-05-21 07:28:59

标签: python class decorator argparse super

首先,这个问题可能是duplicate,但不知何故,我还没有理解这些答案。说我有:

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()以某种方式(不知道如何正确写入)检查时,如果子项添加了任何参数然后离开{{1}到了儿童班。但我想,是否有可能一个愚蠢的想法是改变父亲的self.parser.parse_args()表现得像一个装扮者而不是孩子,并做这样的事情(事实的一部分, init 允许要返回__init__以外的任何内容,它可能不会因各种其他原因而起作用..?)

None

那么,任何想法,我应该选择哪条路?我的动机是,我希望最终用户,谁将使用这样的框架(这意味着编写应用程序,继承自Parent)需要做尽可能少的工作(这意味着,移动)大多数事情变成父母)。有什么合理的方法,怎么做?

1 个答案:

答案 0 :(得分:1)

移动中间'在父类中分配到单独的方法。然后,您可以在子项中覆盖该方法:

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();它被所有需要的东西(由框架预先消化)传递给更新解析器。