1

我编写了一个 python 模块 mymod.py,它也可以用作命令行中的独立程序。

在 mymod.py 中,我定义了一些函数(其中使用关键字设置默认值)和一个if __name__=="__main__"将模块用作独立程序的块。

我希望有可能覆盖一些默认选项,因此在主程序中我import argparse并使用它来解析选项。我使用字典来存储默认值,因此如果有一天我需要更改默认值,我可以很容易地只在一个地方修改它的值。

它有效,但我发现代码不是“干净”的,并认为我可能没有以正确的 Python 方式进行操作。

这是一个展示我所做的玩具示例:

#!/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?

4

2 回答 2

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)

我花了一段时间才让它工作,因为我没有注意到你正在使用destadd_argument我从不使用它)。如果未提供此关键字,则 argparse 将默认设置为dest参数的长名称(在这种情况下f1_x,和f2_x,因为它替换-_)。切入正题:如果你想提供一个默认字典,dest如果提供的话,键需要匹配。此外,请注意parser.set_defaults仅向解析器添加参数,因此如果您的解析器中没有某些条目,它将被添加到Namespace.

kwargs-- 编辑为函数添加泛型--

于 2013-03-22T12:33:38.450 回答
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()如果不带参数调用,将使用它。

这要求 thatNone永远不会是有意义的值x; 如果不是这种情况,请选择一个合适的不可能值。

于 2013-03-22T13:00:44.253 回答