我应该在函数调用的最后一个参数之后添加一个逗号吗?

Posted

技术标签:

【中文标题】我应该在函数调用的最后一个参数之后添加一个逗号吗?【英文标题】:Should I add a trailing comma after the last argument in a function call? 【发布时间】:2012-08-18 17:44:52 【问题描述】:

做什么比较好?

self.call(1, True, "hi")

self.call(1, True, "hi",)

以及在以下情况下:

self.call(
    1,
    True,
    "hi"
)

self.call(
    1,
    True,
    "hi",
)

?

在数据结构中添加尾随逗号的原因我很熟悉,但是函数调用呢?

【问题讨论】:

您能概括一下这些原因吗?我只觉得有必要用 php 来做这件事,而这种语言让我感到很亲切。 我会遵循 PEP8 中的建议 python.org/dev/peps/pep-0008 @TimHoffman:我刚刚浏览了 PEP 8。在那里我找不到与这个问题相关的任何内容 - 你能指出我的相关部分吗? 是的,我以为这个在 PEP8 中,但我一定在其他地方读过。我从来没有在函数/方法定义中留下尾随','或调用它们,但通常将它用于字典和列表。抱歉误导了。 【参考方案1】:

我认为在函数调用中避免使用尾随逗号没有技术上的理由,但有些人可能确实觉得它们会分散注意力。有些人可能会停下来说:

“嗯,我想知道那是否真的应该在那里?”

我不愿将此称为好处,但使用尾随逗号和缩进样式的一个效果使版本控制差异看起来更清晰添加参数。

例如这样的函数:

def my_fun(a, b, c=None):
    ...

...这样称呼:

my_fun(
    a='abc',
    b=123
)

...然后改成这样:

my_fun(
    a='abc',
    b=123,
    c='def'
)

在 git 中产生这个差异:

$ git diff
...
 my_fun(
     a='abc',
-    b=123
+    b=123,
+    c='def'
 )

然而,

my_fun(
    a='abc',
    b=123,
)

改为...

my_fun(
    a='abc',
    b=123,
    c='def',
)

在 git 中产生这个差异:

$ git diff
...
 my_fun(
     a='abc',
     b=123,
+    c='def',
 )

【讨论】:

@icarus74,当您每行限制为 80 列时,这很常见。 +1 我的 5 美分:对多行函数调用使用尾随逗号,就像对多行列表和字典一样。请注意,将尾随逗号与 *-args 组合(例如 f(*args, a, b, ))仅是 allowed from Python 3.5.0 onwards。 从 python3.6 开始:现在允许在带有starargs(*args**kwargs*, kw=...)的函数中使用尾随逗号 diff 示例是在函数调用中使用尾随逗号的有力论据【参考方案2】:

我也会把我的 2 美分留在这里,即使这个帖子已经在这里很长一段时间了,它可能会让某人受益:)

PEP8 实际上确实说 when to use trailing commas 并且如果您遵循他们的建议(不是强制性的,但绝对是推荐),那么您的第二个单行示例可以被裁定出,即:

没有:

self.call(1, True, "hi",)

是的:

self.call(
    1,
    True,
    "hi",
)

函数调用中的用法(谨慎使用以从不使用),原因如下:


编码原则之一是函数应该做一件事,并且只做一件事。因此,看到后面的逗号,可能会出现很多问题,而实际上它们不应该出现。通常,当您在某处看到尾随逗号时,您预计该内容会随时间而变化。因此,如果它是 listtupledict 等,通常表明设计它的人是出于物理添加或删除或切换该数据结构中的行,以及......你不会经常看到函数,或者至少你不应该看到,如果你这样做,应该考虑更好的设计。

如前所述,一个函数也应该是非常可预测的,你不要设计一个同时向月球发送邮件和火箭的函数,并且在调用它时留下一个尾随逗号发送邮件,因为谁知道你什么时候可以发送火箭,并且你想要更少混乱的差异(它只会导致更多的混乱和糟糕的设计)。

任意数量的参数(甚至是固定但大量的参数)通常表明您要么在此处实例化一个对象,要么您正在执行多项操作,当您真正应该做的是将您的设计拆分为创建多个较小的功能时,每个功能都做一件事,因此,不需要尾随逗号

另外考虑一下,即使你确实有一个函数,你可以用多个参数调用它,想想你会多久做一次,这意味着什么?好吧,这意味着:

在调用位置重构代码(可能在另一个函数中,或在模块中或某处),因为通常函数的结果存储在变量中,您需要使用该新结果,因此这意味着重构. 如果它不暗示重构,则表示该函数不返回任何内容,或者返回相同的内容,在这种情况下,这意味着它使用调用中传递的额外参数执行多项操作,如前面说了,不是很理想。

实际使用


尾随逗号是有道理的,就像您在数据结构中所说的那样,数据结构会随着时间的推移发生物理变化,因为如果您在运行时更改它,那么它不会产生任何影响理解编辑器中的任何内容,除了定义可能是一个空结构[]xD

如果数据结构(列表、字典、集合、元组等)预计会发生变化(物理上是源代码),那么实际上建议使用尾随逗号并且实际上很有用(see the full PEP link,它有用例和建议)

结论:


推荐用于预计会发生物理变化的多行数据结构 很少或从不在函数调用中 从不在函数定义中

【讨论】:

我知道这是旧的,但我认为尾随逗号与代码设计完全无关。例如,想想factory functions。创建类的属性可能需要很多参数,因此它可能会定期更改。想想只做一件事但有很多选项的函数,比如this one,以及使用 kwargs 的函数。这类函数会定期更改,可以在这些调用中添加尾随逗号以支持未来的更改。【参考方案3】:

在数据结构中,尾随逗号“有用”,可以更轻松地添加项目:

a = [
      1,
      2,
      3,
    ]

更容易改成

a = [
      1,
      2,
      3,
      4,
      5,
    ]

因为您不必编辑显示3, 的行。

但是在通常不会改变长度的函数调用中没有这样的好处。所以我不鼓励使用尾随逗号。

【讨论】:

为真相+1。那个列表括号缩进风格让我想扯掉我的头发:) 如果函数接受可变数量的参数,结尾的逗号不会有任何影响。 @TimPietzcker:您正在解释数据结构的工作原理。此外,对于我给出的第二个选项,它可能与数据结构一样有用。我的问题更多是关于'哪一个是不可能的?推荐哪一个?' @Kos:你能举个例子吗? @Kos:固定数量的参数也没有什么坏处。但是由于用于调用函数的参数数量很少改变在源代码中(而列表/元组的长度在源代码中经常改变),我没有看到任何实际用途,而且肯定是分散注意力。【参考方案4】:

我认为,在这个问题上,与列表和元组的原因相同,因为函数参数列表正是如此。

以下是针对该语言 (c.f.) 的设计决策的常见问题解答中的引述:

为什么 Python 允许在列表和元组末尾使用逗号?

Python 允许您在列表、元组和字典的末尾添加尾随逗号:

[1, 2, 3,]
('a', 'b', 'c',)
d = 
    "A": [1, 5],
    "B": [6, 7],  # last trailing comma is optional but good style

允许这样做有几个原因。

当列表、元组或字典的字面值分布在多行中时,添加更多元素会更容易,因为您不必记住在前一行添加逗号。这些行也可以重新排序而不会产生语法错误。

意外省略逗号可能会导致难以诊断的错误。例如:

x = [
  "fee",
  "fie"
  "foo",
  "fum"
]

这个列表看起来有四个元素,但实际上包含三个:“fee”、“fiefoo”和“fum”。始终添加逗号可以避免这种错误来源。

允许尾随逗号也可能使程序代码生成更容易。

【讨论】:

【参考方案5】:

这是特定于工具的,但它实际上使 vim/Gvim 中的代码重构更加容易,即使是单行函数参数列表。

def foo(a, b, c, e, d, ):

改为

def foo(a, b, c, d, e, ):

使用 vim 时,您可以删除“e”或“d”,用两次击键 (dW) 移动到要粘贴的位置并按 (p)。

如果您没有结尾逗号,则最终必须将其从新的最后一项中删除,然后将其添加到旧的最后一项中。或者,您必须更加小心地删除直到逗号和更精确地粘贴。使用逗号无处不在,您可以将所有内容视为可以轻松交换的统一块。

Vim 显然在 python 编写者中很受欢迎,所以这实际上似乎有一些优点:https://www.sitepoint.com/which-code-editors-do-pythonists-use/

【讨论】:

以上是关于我应该在函数调用的最后一个参数之后添加一个逗号吗?的主要内容,如果未能解决你的问题,请参考以下文章

esnext:最后一个参数后面也允许加逗号了

如何在除最后一行之外的每一行末尾添加逗号?

帮介绍一下C语言里的varargs。

在 Windows 脚本中读取命令行参数时,有没有办法转义逗号字符?

在 COM 中:我应该在 CoCreateInstance 之后调用 AddRef 吗?

拼接字符串时,去掉最后一个多余的逗号