我正在试图找出在Python3中初始化子/超类的最佳方法。基类和子类都将占用六个参数,所有这些参数都将从命令行参数中解析。
实现这一点的显而易见的方法是一次解析所有的args,并将它们全部传递出去:
class Base:
def __init__(self, base_arg1, base_arg2, base_arg3):
class Sub(Base):
def __init__(self, sub_arg1, sub_arg2, sub_arg3,
base_arg1, base_arg2, base_arg3):
super().__init__(self, base_arg1, base_arg2, base_arg3)
main():
# parse args here
options = parser.parse_args()
obj = Sub(options.sub_arg1, options.sub_arg2, options.sub_arg3,
options.base_arg1, options.base_arg2, options.base_arg3)
如果我有一个Sub-subclass(我会),就通过连续的super()。 init ()调用传递的参数列表而言,事情变得非常毛茸茸。
但是我发现argparse.parse_known_args()提供了另一条路径:我可以让每个子类解析出它需要/识别的参数,并将其余的参数传递给层次结构:
class Base:
def __init__(self, args):
base_options = base_parser.parse_known_args(args)
class Sub(Base):
def __init__(self, args):
(sub_options, other_args) = sub_parser.parse_known_args(args)
super().__init__(self, other_args)
main():
obj = Sub(sys.argv)
从API的角度来看,这似乎更清晰。但是我可以想象它违反了“Python中已经完成的事情”的一些原则,并且出于各种原因这是一个坏主意。我对网络的搜索没有任何一个例子 - Stack Overflow的强大和全知的想法能帮助我理解正确的方法吗?
答案 0 :(得分:0)
查看argparse.py
代码。 ArgumentParser
是_ActionsContainer
的子类。所有actions
都是Action
的子类。
致电时
parser.add_argument('foo', action='store_action', ...)
将参数传递给*args
和**kwargs
到_StoreAction
,然后将它们传递给supper
(在设置一些默认值之后等)
作为一个意味着要导入的模块,并且永远不会作为脚本运行,它没有if __name__....
块。但通常我会包含这样一个块来调用测试代码。这是放置命令行解析器的地方,或者至少是调用它的地方。如果可能在正文中的函数中定义,但通常在导入模块时不应调用它。
一般来说,argparse
是一个脚本工具,不应该成为类定义的一部分 - 除非您是一个子类ArgumentParser
来添加一些新功能。
您可能还想查看https://pypi.python.org/pypi/plac。这个包为argparse
提供了一个不同的接口,是子解析这个解析器的一个很好的例子。
答案 1 :(得分:0)
谢谢你!我认为你的回答帮助我弄清楚了一个更简单的方法。我可以解析顶层的所有选项,然后只传递选项命名空间,让每个子类拉出它需要的那些。与其他方法相比,面部手掌简单:
class Base:
def __init__(self, options):
base_arg1 = options.base_arg1
base_arg2 = options.base_arg2
class Sub(Base):
def __init__(self, options):
super().__init__(self, options) # initialize base class
sub_arg1 = options.sub_arg1
sub_arg2 = options.sub_arg2
main():
options = parser.parse_args()
obj = Sub(options)