当我处理也可以从命令行解析的模块的默认参数时,如何避免冗余?
How can I avoid redundancy when I handle default arguments to modules that may also be parsed from the command line?
我正在尝试找到一种好方法来避免我的 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' 参数指定默认值的冗余。除了审美上的烦恼,我倾向于担心,在可能由许多开发人员通过版本控制编辑的较大模块中,可以更改其中一个默认值,但不能更改另一个。
有没有什么好的方法可以消除在两个不同地方指定默认值的冗余?
首先,定义 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
/[ 的定义中)更改它们=17=] 并在参数列表中 funky
).
或者,如果您使用 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 中,"inspect" 块会更清晰一些:
[...]
funky_params = inspect.signature(funky).parameters.values()
defaults = {p.name: p.default for p in funky_params if p.default is not p.empty}
[...]
我正在尝试找到一种好方法来避免我的 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' 参数指定默认值的冗余。除了审美上的烦恼,我倾向于担心,在可能由许多开发人员通过版本控制编辑的较大模块中,可以更改其中一个默认值,但不能更改另一个。
有没有什么好的方法可以消除在两个不同地方指定默认值的冗余?
首先,定义 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
/[ 的定义中)更改它们=17=] 并在参数列表中 funky
).
或者,如果您使用 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 中,"inspect" 块会更清晰一些:
[...]
funky_params = inspect.signature(funky).parameters.values()
defaults = {p.name: p.default for p in funky_params if p.default is not p.empty}
[...]