有时为参数而不是参数对象传递复杂的字典是更好的做法吗?

Mat*_*ell 3 python parameters arguments

我已经使用 Python 编程一年了,来自 Java 背景,我注意到,至少在我的组织中,将复杂参数传递给函数的风格是使用字典或元组,而不是一个专门的参数类。例如,我们有一个方法,它接受三个字典,每个字典都以特定的方式构造,每个字典本身都被格式化为元组。构建 args 和阅读代码对我来说很复杂。下面是一个传递参数的例子:

{'[A].X': ((DiscreteMarginalDistribution, ('red', 'blue')), ()),
 '[A].Y': ((DiscreteConditionalDistribution, ('yellow', 'green'), ('red', 'blue')),
           (IdentityAggregator('[A].X'), ))
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 像这样传递字典/元组是一种常见的 Python 习语吗?
  2. 如果有的话,您何时编写 Python 代码来使用后者(参数实例)?例如,当嵌套结构超过某个复杂性阈值时。

提前致谢!

Jan*_*cke 5

  • 是的,通常将字典传递给 Python 函数以减少参数的数量。具有正确键命名的字典式配置比仅使用元组更具可读性。

  • 我认为动态构建自定义配置类的专用实例相当罕见。我会坚持使用字典。如果您的 config dict 和它的使用者不同步,您会得到KeyErrors,这非常适合调试。

一些建议和推理:

如果您的应用程序的某些部分需要非常复杂的配置,我认为拥有一个正确表示当前配置的配置对象是个好主意。但是,在我的项目中,我从未最终将此类对象作为函数参数传递。这闻起来。在某些应用程序中,我有一个恒定的全局配置对象,在引导期间设置。这样的对象是全局可用的,并被视为“不可变的”。

单个函数永远不应该复杂到需要检索极其复杂的配置。这表明您应该将您的代码分成几个组件,每个子单元都有一个相当简单的参数化。

如果函数的运行时配置比普通(关键字)参数容易处理的复杂度更高,则传递字典是绝对常见的,可以说是“轻量级”配置对象。一个经过深思熟虑的关键名称选择使这种方法具有很好的可读性。当然,您也可以建立一个层次结构,以防您的用例使用一个级别不够。

最重要的是,请注意,在许多情况下,最好的方法是使用正常的参数规范通过签名显式定义函数的参数化:

def f(a, b, c, d, e):
    ...
Run Code Online (Sandbox Code Playgroud)

在调用代码中,您可以在字典中为这些参数准备值:

arguments = {
    a = 1,
    b = 2,
    c = 3,
    d = 4,
    e = "x"
}
Run Code Online (Sandbox Code Playgroud)

然后在函数调用时使用 Python 的语法糖进行关键字扩展:

f(**arguments)
Run Code Online (Sandbox Code Playgroud)

  • 因为 Python 对象比简单的字典引入了额外的复杂性。如果您不需要那种复杂性,那为什么要使用它呢?超出要求的复杂性是一个糟糕的设计选择。请不要使用对象,因为 `obj.attr` 看起来比 `d["attr"]` 好看。 (3认同)
  • 首选始终是具有明确定义的函数调用签名。特别是在您设计公共 API 的情况下。这可能会变得复杂,但它*明确*并且仍然易于阅读。例如,极端情况是 matplotlib API:http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.bar 或 pandas API:http://pandas.pydata.org/pandas-docs/version /0.15.1/generated/pandas.io.parsers.read_csv.html#pandas-io-parsers-read-csv (2认同)