我试图找到一种很好的方法来避免冗余(可能会产生分歧的风险)到我的python模块,可以从命令行执行。
考虑一个像这样的python模块:
#!/usr/bin/env python2.7
from argparse import ArgumentParser
DEFAULT_A_ARG='alpha'
def funky(a=DEFAULT_A_ARG, b=False):
pass
if __name__ == '__main__':
parser = ArgumentParser()
parser.add_argument('-a', default=DEFAULT_A_ARG)
parser.add_argument('-b', action='store_true', default=False)
args = parser.parse_args()
funky(a=args.a, b=args.b)
因此,使用此模块的人可以将其导入自己的代码或从命令行调用它。我不希望在指定' a'的默认值时存在冗余。函数定义和命令行解析器之间的参数。除了审美烦恼之外,我倾向于担心,在可能通过许多开发人员的版本控制进行编辑的较大模块中,其中一个默认值可以更改,但不能更改另一个。
有没有一种好方法可以消除在两个不同位置指定默认值的冗余?
答案 0 :(得分:1)
或者,如果您使用ArgumentDefaultsHelpFormatter通过使用消息显示默认值,则可以执行以下操作:
#!/usr/bin/env python2.7
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
parser = ArgumentParser(prog='my_program',
formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument('-a', default='alpha', help='your favorite greek letter')
parser.add_argument('-b', action='store_true', help='print numbers in binary format')
def funky(a=parser.get_default('a'), b=parser.get_default('b')):
pass
if __name__ == '__main__':
args = parser.parse_args()
funky(**args.__dict__)
在终端上:
$ my_program.py --help
usage: my_program [-h] [-a A] [-b]
optional arguments:
-h, --help show this help message and exit
-a A your favorite Greek letter (default: alpha)
-b print number in binary format (default: False)
你定义它一次并在三个不同的地方得到它,没有常数或者调用函数体......
我对恢复功能元数据知之甚少。所以,阅读文档对于回答这个问题非常有帮助。如果可以,请查看标准库的inspect模块...
这是另一种可能性,在函数定义中指定参数默认值:
#!/usr/bin/env python2.7
from argparse import ArgumentParser
def funky(x, a='alpha', b=False):
pass
if __name__ == '__main__':
import argparse
import inspect
funky_spec = inspect.getargspec(funky)
defaults = funky_spec.defaults
defaults = dict(zip(funky_spec.args[-len(defaults):], defaults))
# effect: ['x', 'a', 'b'] + ('alpha', False) -> {'a': 'alpha', 'b': False}
parser = argparse.ArgumentParser()
parser.add_argument('x', help='input number')
parser.add_argument('-a', default=defaults['a'])
parser.add_argument('-b', action='store_true', default=defaults['b'])
args = parser.parse_args()
funky(x=args.x, a=args.a, b=args.b)
在Python 3中,"检查"块会更清晰:
[...]
funky_params = inspect.signature(funky).parameters.values()
defaults = {p.name: p.default for p in funky_params if p.default is not p.empty}
[...]
答案 1 :(得分:0)
首先,将funky
定义为使用None
作为默认参数:
def funky(a=None, b=None):
if a is None:
a = DEFAULT_A_ARG
if b is None:
b = False
然后,让None
成为每个命令行参数的默认值:
if __name__ == '__main__':
parser = ArgumentParser()
# You probably don't have to specify a default of None explicitly
parser.add_argument('-a', default=None)
parser.add_argument('-b', action='store_true', default=None)
args = parser.parse_args()
funky(a=args.a, b=args.b)
如果要更改实际默认值,您只需要在一个位置(funky
的主体内)而不是两个位置(在-a
/ {{1的定义中)更改它们并且在参数列表中-b
)。