正确使用与过度使用Python中的* args

时间:2012-09-19 23:41:01

标签: python arguments maintainability

我一直在查看我正在使用的开源软件包的源代码。几乎每个函数都使用* args而不是命名参数。我发现很难遵循和使用代码,因为每次我想调用一个函数我都要回去,选择源代码,并确定参数应该是什么,以及它们应该在什么顺序。我的问题是:有没有令人信服的理由在每个函数中使用* args,或者这是对这个概念的滥用? 谢谢, -b

5 个答案:

答案 0 :(得分:4)

这可能是个人推理,但是当我有很多可选字段时,我只使用* args和** kwargs,其中某些字段仅用于特定上下文。

我使用args的另一个场合是我为云API构建XML RPC客户端。由于我只是将参数传递给底层,而且由于动态生成的函数,我没有其他选择,只能使用* args,因为我无法事先知道所有参数。

在大多数情况下,您甚至不需要它。我认为它主要是懒惰而不是其他任何东西。

有些来自Java和C#的人可能会用它来代替“params”,但是有很多方法可以在python中传递可选参数。

我同意即使你使用* args,你也应该有一份非常好的文档。

答案 1 :(得分:3)

在每个函数中使用*args是一个坏主意,因为它可以掩盖代码中的错误(调用具有错误数量的参数的函数)。我认为,如果您需要 *args,经验法则应该只使用*args

答案 2 :(得分:3)

Zen of Python中,我们被告知更喜欢显式过度隐含。应尽可能使用明确的参数。

答案 3 :(得分:2)

如果没有令人信服的理由使用*args,那就是滥用这个概念。通常有很好的参数名称,这有助于理解。即使没有,(x, y, z)会告诉您超过(*args)

除了使代码更具可读性之外,它还有助于捕获错误(例如,如果您使用(x, y, z)调用(2, 3)函数,则会在调用时收到错误,而不是在内部功能),它通常更简洁,甚至可以更有效。

但有时候有充分理由广泛使用*args

例如,如果您要包装较低级别(C或其他)模块并希望进行完美转发,则使用*args会更容易。如果您自动生成包装器代码而不是手动编写它,则更是如此。当然,这仍然是一种权衡 - 对包装器模块的开发人员来说更容易,但对用户来说更难 - 但有时需要权衡取舍。

在不知道您所指的特定包裹的情况下,无法猜测这是一个令人信服的用例还是滥用。

答案 4 :(得分:2)

如果你要包装一个未知函数(装饰器返回的函数经常这样做),那么你经常需要使用(*args, **kwargs)

某些类层次结构在方法中使用(*args, **kwargs),这些方法可能需要层次结构中不同类的不同签名(__init__是罪魁祸首)。如果你可以避免这种情况,真的很有帮助,但是可能需要以理智的方式使用多个继承层次结构(或者至少在多重继承的情况下保持理智)。

当我有大量可选参数时,我有时最终会使用**kwargs,但这需要大量文档。

在一个消耗*args本身的函数中(而不是将它们传递给具有未知签名的其他函数,如在装饰器或类继承案例中),那么我倾向于认为*args应该几乎不会被使用,除非意味着“零或更多相同的东西”。在这种情况下,您应该将其命名为*websites*spaceships*watermelons,而不是*args。一堆不相关的参数不应该被压缩到*args。更糟糕的是,函数使用*args来获取“x,y和z,或者x和z”,其中第二个参数根据传递的参数数量做不同的事情。那时他们应该显然都有名称和默认值(即使它只是标准None默认值,然后在函数中看到哪些是非None模式)并且通过关键字而不是位置传递

相关问题