我编写了一个python模块mymod.py,它也可以作为命令行的独立程序使用。
在mymod.py中我定义了一些函数(使用关键字设置默认值)
和if __name__=="__main__"
块将模块用作独立程序。
我希望有可能覆盖一些默认选项,因此在主程序I import argparse
中使用它来解析选项。我用字典来存储
默认值,所以如果有一天我需要更改默认值,我可以轻松
只在一个地方修改它的价值。
它有效,但我发现代码不是“干净”,并且认为我可能不会以适当的pythonic方式进行。
这是一个展示我所做的玩具示例:
#!/usr/bin/env python
#mymod.py
__default_options__={
"f1_x":10,
"f2_x":10
}
def f1(x=__default_options__["f1_x"]):
return x**2
def f2(x=__default_options__["f2_x"]):
return x**4
# this function is the "core" function which uses f1 and f2
# to produce the main task of the program
def f(x=__default_options__["f1_x"],y=__default_options__["f2_x"]):
return f1(x)+f2(y)
if __name__=="__main__":
import argparse
parser = argparse.ArgumentParser(description = "A toy application")
parser.add_argument("--f1-x",help="the parameter passed to f1",
default=__default_options__["f1_x"], type = float,dest = "x")
parser.add_argument("--f2-x",help="the parameter passed to f2",
default=__default_options__["f2_x"], type = float, dest = "y")
options= parser.parse_args()
print f(options.x,options.y)
像我这样传递默认值有点麻烦,可能违背了Python和argparse的精神。
如何将此代码改进为pythonic并最好使用argparse?
答案 0 :(得分:1)
您可以按以下方式使用`ArgumentParser.set_defaults方法
default_options={
"x":10,
"y":10
}
def f1(**kwargs):
x=kwargs.get('x', defalut_options['x'])
return x**2
def f2(**kwargs):
y=kwargs.get('y', defalut_options['y'])
return x**4
def f(**kwargs):
x=kwargs.get('x', defalut_options['x'])
y=kwargs.get('y', defalut_options['y'])
return f1(x=x, y=y)
if __name__=="__main__":
import argparse
parser = argparse.ArgumentParser(description = "A toy application", formatter_class=argparse.ArgumentDefaultsHelpFormatter )
parser.add_argument("--f1-x",help="the parameter passed to f1",
type = float,dest = "x")
parser.add_argument("--f2-x",help="the parameter passed to f2",
type = float, dest = "y")
parser.set_defaults(**default_options)
options= parser.parse_args()
print f(options.x,options.y)
我花了一段时间才能使它工作,因为我没有注意到你在dest
中使用add_argument
(我从不使用它)。如果未提供此关键字,则argparse将默认dest
设置为参数的长名称(在本例中为f1_x
和f2_x
,因为它将-
替换为{{ 1}})。要说明一点:如果要提供默认字典,则密钥需要与_
匹配(如果提供)。另外,请注意dest
只是向解析器添加参数,因此如果您的解析器中没有某些条目,它将被添加到parser.set_defaults
。
- 已编辑以将通用Namespace
添加到函数 -
答案 1 :(得分:1)
正如@Francesco在评论中写道,你的默认词典不会像你想要的那样工作:这些函数将保留加载模块时的默认值,而不管以后对字典的更改。以下是如何使它们跟踪字典的当前值:
_default_options = {
"f1_x":10,
"f2_x":10
}
def f1(x=None):
if x == None:
x = _default_options["f1_x"]
...
然后,您可以通过_default_options
或以任何其他方式修改ArgumentParser
,如果没有参数调用,f1()
将使用它。
这要求None
永远不会成为x
的有意义值;如果不是这样,请选择合适的不可能值。