45

做什么比较好?

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

或者

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

以及在以下情况下:

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

或者

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

?

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

4

5 回答 5

51

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

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

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

例如,这样的函数:

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',
 )
于 2013-07-05T15:14:37.613 回答
25

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

PEP8实际上确实说明了何时使用尾随逗号,并且如果您遵循他们的建议(不是强制性的,但绝对推荐),那么可以排除您的第二个单行示例,即:

不:

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

是的:

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

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


  • 编码原则之一是函数应该做一件事,而且只做一件事。因此,看到后面的逗号,可能会出现很多问题,而实际上它们不应该出现。通常,当您在某处看到尾随逗号时,您会期望该内容会随着时间而改变。因此,如果它是一个listtupledict等,它通常表明无论是谁设计它,都是为了在该数据结构中物理添加、删除或切换行,而且......你看不到功能非常频繁,或者至少你不应该,如果你这样做,应该考虑更好的设计。

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

  • 任意数量的参数(甚至是固定但大量的参数)通常表明您要么在那里实例化一个对象,要么您正在做多个事情,而实际上您应该做的是将您的设计拆分为创建多个较小的函数,每个函数只做一件事,因此不需要尾随逗号

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

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

实际用途


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

  • 如果数据结构(列表、字典、集合、元组等)预计会发生变化(实际上是源代码),那么实际上建议使用尾随逗号并且实际上很有用(请参阅完整的 PEP 链接,它有用例和建议)

结论:


  • 推荐用于预期会发生物理变化的多行数据结构
  • 很少在函数调用中
  • 从不在函数定义中
于 2018-04-04T15:23:41.967 回答
15

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

a = [
      1,
      2,
      3,
    ]

更容易变成

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

因为您不必编辑3,.

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

于 2012-08-23T08:38:44.543 回答
9

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

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

为什么 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”。始终添加逗号可以避免这种错误来源。

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

于 2015-12-14T19:02:37.013 回答
2

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

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

变成

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

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

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

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

于 2019-10-25T15:52:06.373 回答