Python 修改后将*args、**kwargs传递给父类
基于a,我实现了以下修改的Python 修改后将*args、**kwargs传递给父类,python,Python,基于a,我实现了以下修改的argparse.Action,它生成键值对 我想允许动态设置nargs,并提供选项,在键可能出现多次的情况下使用defaultdict(list) 以下是我的实施方案: import argparse from collections import defaultdict class NamespaceAction(argparse.Action): """ This modified action allows me to group togeth
argparse.Action
,它生成键值对
我想允许动态设置nargs
,并提供选项,在键可能出现多次的情况下使用defaultdict(list)
以下是我的实施方案:
import argparse
from collections import defaultdict
class NamespaceAction(argparse.Action):
"""
This modified action allows me to group together key-value pairs passed to an argument.
Extended to produce a defaultdict(list) if requested, so that a key can appear more than once.
"""
def __init__(self, *args, **kwargs):
self.nargs = kwargs.get('nargs', 1)
self.mode = kwargs.get('mode', 'dict') # default mode is dict
super(NamespaceAction, self).__init__(*args, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
# The default value is often set to None rather than an empty list.
current_arg_vals = getattr(namespace, self.dest, []) or []
setattr(namespace, self.dest, current_arg_vals)
arg_vals = getattr(namespace, self.dest)
try:
if self.mode == 'dict':
arg_vals.append(argparse.Namespace(**dict(v.split('=') for v in values)))
elif self.mode == 'defaultdict':
d = defaultdict(list)
for v in values:
v = v.split('=')
d[v[0]].append(v[1])
arg_vals.append(argparse.Namespace(**d))
else:
raise NotImplementedError("only dict or defaultdict")
except TypeError:
raise RuntimeError('Group {} appears to be incorrectly formatted'.format(values))
但是,使用此选项会导致TypeError:\uuuu init\uuuu()获得意外的关键字参数“mode”
。但是,如果我从args/kwargs中删除模式
和dict
,它仍然不起作用:
def __init__(self, *args, **kwargs):
self.nargs = kwargs.get('nargs', 1)
self.mode = kwargs.get('mode', 'dict') # default mode is dict
if 'mode' in kwargs:
del kwargs['mode']
if 'nargs' in kwargs:
del kwargs['nargs']
super(NamespaceAction, self).__init__(*args, **kwargs)
导致TypeError:\uuuu init\uuuu()至少接受3个参数(给定1个)
我如何让这个类接受参数,并且仍然正确地初始化父类?您希望
nargs
具有位置性,但它是一个可选参数;根据文件:
Action类必须接受两个位置参数加上传递给ArgumentParser的任何关键字参数。除了Action
本身之外,添加_argument()
您可以尝试:
def __init__(self, *args, **kwargs):
# To force nargs, look it up, but don't bother setting on self;
# just let it pass to the parent, if you remove it from kwargs, the
# parent __init__ overwrites self.nargs with None
nargs = kwargs['nargs']
assert isinstance(nargs, int) or nargs == "+"
# dict.pop is like get, but removes the mapping if it exists
self.mode = kwargs.pop('mode', 'dict') # Will use 'dict' as default
# Pass along remaining arguments
super(NamespaceAction, self).__init__(*args, **kwargs)
考虑到
操作。\uuuuu init\uuuu
采用两个位置参数,option\u strings
和dest
,假设NamespaceAction
的第一个位置参数是参数数似乎是个坏主意,如果不是错误的话。True,我可以将其更改为另一个关键字参数。这仍然会导致错误TypeError:\uuu init\uuuu()至少接受3个参数(给定1个)
。不过,我用错了。我需要在add_argument
中使用kwargs,而不是action=NamespaceAction()
@IanFiddes:您确定吗?我不能复制。我确实看到了一个缺陷(您正在拦截nargs
参数,因此对象的repr
表示它是None
,即使传递时也是如此,因为parent\uuuuuu init\uuuuu
上的默认参数会覆盖它;您可以忽略nargs
,让父类\uuuu init\uuu
处理它,然后检查以确保self。nargs
之后是非None
),但在我使用解析器时,它可以正常工作。添加_参数('foo',action=NamespaceAction,nargs=12)
,这是调用NamespaceAction.\uuuu init\uuuu
的地方。回溯是否显示代码的\uuuu init\uuuuu
有问题?@IanFiddes:是的,应该是action=NamespaceAction
,没有参数。很高兴你找到了。