在元组定义中使用逗号结尾的语法规则是什么?


Answers:


73

在所有情况下,除了空的元组,逗号都是重要的事情。仅在出于其他语法原因而需要时才需要括号:将元组与一组函数参数,运算符优先级区分开或允许换行。

元组,列表或函数参数的尾部逗号是一种不错的样式,尤其是当您有一个较长的初始化并分为多行时。如果始终包含尾随逗号,则不会在末尾添加任何行,而期望添加另一个元素,而只是创建一个有效的表达式:

a = [
   "a",
   "b"
   "c"
]

假设它最初是一个2元素列表,后来又进行了扩展,那么它可能以一种可能并不立即显而易见的方式出错了。始终包含结尾逗号,这样可以避免出现陷阱。


3
由于上述原因,用逗号隔开可能是有利的。另一方面,如果您还在应用程序中的其他地方处理JavaScript或JSON,则养成这种习惯可能会导致头痛,因为某些浏览器在那里不喜欢它。
Cito

7
是的,但是,您永远不应该手工构造JSON,这样就没关系了,对于Javascript,请始终使用jslint或类似的方法在接近浏览器之前捕获此类错误。
邓肯,

100

只有单项元组才需要消除定义元组或由括号包围的表达式的歧义。

(1)  # the number 1 (the parentheses are wrapping the expression `1`)
(1,) # a 1-tuple holding a number 1

对于一个以上的项目,不再需要了,因为显然它是一个元组。但是,允许使用逗号逗号来简化使用多行定义它们的过程。您可以在不破坏语法的情况下添加到末尾或重新排列项目,因为您偶然遗漏了逗号。

例如,

someBigTuple = (
                   0,
                   1,
                   2,
                   3,
                   4,
                   5,
                   6,
                   7,
                   8,
                   9,
                   10,
                   #...
                   10000000000,
               )

请注意,这也适用于其他集合(例如列表和字典),而不仅仅是元组。


5
+1指出这对于除元组以外的其他内容也有效。这对于key: value,每行只有一个非常有用,并且在添加新内容时不会用逗号打扰。
乔尔

46

尾随逗号的另一个优点是,它使差异看起来更好。如果您从

a = [
    1,
    2,
    3
]

并将其更改为

a = [
    1,
    2,
    3,
    4
]

差异看起来像

 a = [
     1,
     2,
-    3
+    3,
+    4
 ]

而如果您以逗号开头,例如

a = [
    1,
    2,
    3,
]

然后差异将是

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

这实际上是对原始问题的回答,而不是答案。
疯狂物理学家


8

另外,请考虑所需的情况:

>>> (('x','y'))*4                         # same as ('x','y')*4
('x', 'y', 'x', 'y', 'x', 'y', 'x', 'y')
#Expected = (('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))

因此,在这种情况下,外部括号仅是对括号进行分组。要使它们成为元组,您需要添加尾随逗号。即

>>> (('x','y'),)*4 
(('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))

6

仅尾元素元组才需要尾随逗号。对于较大的元组,用逗号结尾是一个样式问题,并非必需。它的最大优点是对带有经常修改的多行大元组(例如配置元组)的文件进行完全比较。


6

这是一个简单的答案。

a =(“ s”)是一个字符串

a =(“ s”,)是具有一个元素的元组。

对于一个元素元组,Python需要附加逗号,以区分字符串和元组。

例如,在python控制台上尝试:

a =(“ s”)

a = a +(1,2,3)

追溯(最近一次通话):

文件stdin,第1行,在模块中

TypeError:无法连接“ str”和“ tuple”对象


4

存在的另一个原因是它使代码生成和__repr__功能更易于编写。例如,如果您有一些构建为的对象obj(arg1, arg2, ..., argn),则可以这样写obj.__repr__

def __repr__(self):
    l = ['obj(']
    for arg in obj.args: # Suppose obj.args == (arg1, arg2, ..., argn)
        l.append(repr(arg))
        l.append(', ')
    l.append(')')
    return ''.join(l)

如果不允许使用逗号结尾,则必须对最后一个参数进行特殊处理。实际上,您可以使用列表理解将上述内容写在一行中(我将其写得更长一些,以便于阅读)。如果上学期不得不特殊情况,要做到这一点并非易事。


2
无需对最后一个参数进行特殊处理,只需join在这种情况下使用即可def __repr__(self): 'obj(' + ', '.join([repr(arg) for arg in obj.args]) + ')'
苏珊·杜彭(SuzanneDupéron)2013年

它也有助于代码生成,甚至可以使用非Python编写的工具,也不能使用join
asmeurer 2013年

2

PEP 8-Python代码样式指南-何时使用尾随逗号

尾部的逗号通常是可选的,但当组成一个元素的元组时它们是必需的(并且在Python 2中,它们具有print语句的语义)。为了清楚起见,建议将后者用(技术上多余的)括号括起来。

是:

FILES = ('setup.cfg',)

好的,但是令人困惑:

FILES = 'setup.cfg',

如果结尾的逗号多余,则在使用版本控制系统时,当值,参数或导入项的列表预计会随着时间扩展时,它们通常会很有用。模式是将每个值(等)单独放在一行上,始终添加尾随逗号,并在下一行上添加右括号/括号/括号。但是,在与结束定界符相同的行上使用尾随逗号是没有意义的(在上述单例元组的情况下除外)。

是:

FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )

没有:

FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

-5

编码风格是您的喜好,如果您认为编码标准很重要,那么可以使用PEP-8指导您。

您如何看待以下表达的结果?

x = (3)
x = (3+2)
x = 2*(3+2)

是的,x只是一个数字。


1
那是解释你思路的糟糕方法。显式胜于隐式。
Guilherme David da Costa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.