【问题标题】:How to decorate (wrap) child's method with parent's method如何用父母的方法装饰(包装)孩子的方法
【发布时间】:2016-09-18 12:19:23
【问题描述】:

首先,这个问题可能是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() 或者它会以某种方式(现在不知道如何准确地写)检查,如果孩子添加了任何参数,然后将self.parser.parse_args() 留给孩子类。但我想,是否有可能一个愚蠢的想法是改变父母的__init__ 表现得像孩子的装饰者并做这样的事情(事实的一部分, init 确实允许返回除了None 之外的任何东西,它可能由于各种其他原因无法正常工作..?)

class Child(Parent):
    @super.__init__
    def __init__(self):

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

【问题讨论】:

  • 如果所有功能都在__init__ 中,你为什么要为此使用一个类?您是否考虑过拆分设置和解析,所以您的最后一行将是例如Child().parse()?
  • @jonrsharpe 这只是一个开始,我想进一步扩展它。

标签: python class decorator argparse super


【解决方案1】:

将父类中的“中间”部分移出到 separate 方法。然后,您可以在子级中覆盖 just 该方法:

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();它被框架预先消化,以更新解析器。

【讨论】:

  • 谢谢,太好了。我不知道,为什么我如此渴望将它包含在 __init__ 中,也许是因为我认为这是应用程序的设置(它是).. 只是一个附带问题:你会用这个吗自己编码 ?这是一种好的做法吗?
  • @quapka:我不会使用它,不,因为通常对于我的用例来说已经有可用的东西了。我会在main() 函数 中使用argparse,对于更复杂的命令行需要使用click,或者使用特定于上下文的工具,例如Flask-Scriptadd a Django command
猜你喜欢
  • 1970-01-01
  • 2022-01-16
  • 2019-11-03
  • 1970-01-01
  • 2014-12-29
  • 2013-05-23
  • 2020-01-11
  • 2020-12-28
  • 1970-01-01
相关资源
最近更新 更多