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

tap*_*per 22 python coding-style function parameter-passing

什么是更好的做法?

self.call(1, True, "hi")
Run Code Online (Sandbox Code Playgroud)

要么

self.call(1, True, "hi",)
Run Code Online (Sandbox Code Playgroud)

以下情况如下:

self.call(
    1,
    True,
    "hi"
)
Run Code Online (Sandbox Code Playgroud)

要么

self.call(
    1,
    True,
    "hi",
)
Run Code Online (Sandbox Code Playgroud)

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

Jac*_*Wan 36

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

"嗯,我想知道那真的应该在那儿吗?"

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

例如,这样的函数:

def my_fun(a, b, c=None):
    ...
Run Code Online (Sandbox Code Playgroud)

......这样叫:

my_fun(
    a='abc',
    b=123
)
Run Code Online (Sandbox Code Playgroud)

...然后改为:

my_fun(
    a='abc',
    b=123,
    c='def'
)
Run Code Online (Sandbox Code Playgroud)

在git中生成这个diff:

$ git diff
...
 my_fun(
     a='abc',
-    b=123
+    b=123,
+    c='def'
 )
Run Code Online (Sandbox Code Playgroud)

然而,

my_fun(
    a='abc',
    b=123,
)
Run Code Online (Sandbox Code Playgroud)

变成...

my_fun(
    a='abc',
    b=123,
    c='def',
)
Run Code Online (Sandbox Code Playgroud)

在git中生成这个diff:

$ git diff
...
 my_fun(
     a='abc',
     b=123,
+    c='def',
 )
Run Code Online (Sandbox Code Playgroud)

  • diff 示例是在函数调用中使用尾随逗号的有力论据 (8认同)
  • +1 我的 5 美分:对多行函数调用使用尾随逗号,就像对多行列表和字典一样。请注意,仅[从 Python 3.5.0 开始允许](https://bugs.python.org/issue9232) 将尾随逗号与 *-args 组合(例如 `f(*args, a, b, )`)。 (4认同)
  • 从python3.6开始:在具有starargs(`* args`,`** kwargs`,`*,kw = ...`)的函数中现在允许使用逗号 (2认同)

Tim*_*ker 12

在数据结构中,尾随逗号对于更容易添加项目是"有用的":

a = [
      1,
      2,
      3,
    ]
Run Code Online (Sandbox Code Playgroud)

更容易改变

a = [
      1,
      2,
      3,
      4,
      5,
    ]
Run Code Online (Sandbox Code Playgroud)

因为您不必编辑所说的行3,.

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

  • 如果函数接受可变数量的参数,则尾随逗号不会受到影响. (4认同)

Mar*_*icu 10

我还将把我的2美分留在这里,即使这个线程已经在这里呆了很长时间了,它也可能使某人受益:)

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

没有:

self.call(1, True, "hi",)
Run Code Online (Sandbox Code Playgroud)

是:

self.call(
    1,
    True,
    "hi",
)
Run Code Online (Sandbox Code Playgroud)

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


  • 编码原则之一是,一个函数应该做一件事,而只能一件事。因此,在那里看到尾随的逗号时,可能会出现很多问题,而实际上却不是。通常,当您在某处看到尾随逗号时,您会期望该东西会随着时间改变。因此,如果它是一个listtupledict等,它通常表明是设计它的人,是出于在该结构中实际添加或删除或切换行的目的而设计的,而且...您不会在函数中看到它那么多,或者至少不应该,如果可以,则应该考虑一个更好的设计。

  • 如前所述,一个功能也应该是非常可预测的,您不能设计一个用于同时向月球发送邮件和火箭的函数,并且在调用发送邮件时留下尾随逗号,因为谁知道您什么时候可以发送火箭而且您希望减少比较混乱的差异(这只会造成更多混乱,并且设计不佳)

  • 一个参数的任意数量(甚至是固定的,但大量的参数),通常说明你是有实例化对象,或者你正在做多件事情的时候,确实是你应该做的是你的设计分成创建多个较小函数,每个函数都做一件事情,因此不需要尾随逗号

  • 还要考虑,即使您确实有一个函数,也可以使用多个参数来调用它,但请考虑一下该函数执行的频率及其含义是什么?好吧,这意味着:

    • 这意味着在调用位置(可能在另一个函数中,在模块中或某个地方)重构代码,因为通常将函数的结果存储在变量中,并且您需要使用该新结果,这意味着重构。
    • 如果它不意味着重构,则意味着该函数不返回任何东西,或者确实返回相同的东西,在这种情况下,这意味着它使用调用中传递的额外参数来执行多项操作,如前所述,不是很理想。
    • 即使您不关心编码原理,而忽略上述内容,该操作还会执行多久?如果答案是经常的,那就是另一个糟糕的,不稳定的设计实现。并且,如果不是很频繁(它很好地回答了它本身不应该存在的问题,即使您认为应该这样做,我也认为您的眼睛可以在版本控制差异中多留一行,以便避免在共享您的项目的人员中引起了额外的混乱。

实际用法


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

  • 如果预期数据结构(列表,字典,集合,元组等)会发生变化(从物理上讲是源代码),则实际上建议并使用逗号结尾(实际上是有用的)(请参阅完整的PEP链接,其中包含用例和建议)

结论:


  • 在预期会发生物理变化的多行数据结构中推荐使用
  • 很少在函数调用中永远不会
  • 在函数定义中从不


moo*_*eep 5

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

这是FAQ中有关该语言(cf)的设计决策的引文:

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

Python使您可以在列表,元组和字典的末尾添加尾随逗号:

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

允许这样做有几个原因。

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

不小心忽略逗号会导致难以诊断的错误。例如:

x = [
  "fee",
  "fie"
  "foo",
  "fum"
]
Run Code Online (Sandbox Code Playgroud)

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

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