【问题标题】:When are parentheses required around a tuple?元组周围什么时候需要括号?
【发布时间】:2013-04-07 17:20:44
【问题描述】:

在需要或不需要用括号括起来的元组时,是否有精确定义的引用?

这是一个最近让我吃惊的例子:

>>> d = {}
>>> d[0,] = 'potato'
>>> if 0, in d:
  File "<stdin>", line 1
    if 0, in d:
        ^
SyntaxError: invalid syntax

【问题讨论】:

  • 我发现for k, in d: print k 在这种情况下确实有效。
  • Python grammar 将向您展示 允许的内容,例如,在 if 语句中。您必须通读完整的语法才能确定接受无括号元组的位置,这就是为什么我不将此作为答案发布的原因。
  • ...我不明白您怎么可能对for 失败而0, 感到惊讶... python 标识符必须以(unicode)开头字母或下划线和0 不是有效的python 标识符,因此我会期望在那里有SyntaxError

标签: python syntax tuples


【解决方案1】:

使用逗号标记创建元组的表达式组合称为expression_listoperator precedence 的规则不包括表达式列表;这是因为表达式列表本身不是表达式;括在括号中时它们成为表达式。

因此,在 Python 中语言语法明确允许的任何地方都允许使用未封闭的expression_list,但不允许在需要expression 的地方。

例如if statement的语法如下:

if_stmt ::=  "if" expression ":" suite
             ( "elif" expression ":" suite )*
             ["else" ":" suite]

因为引用了产生式expression,所以不允许未封闭的expression_lists 作为if 语句的主题。但是,for statement 接受 expression_list

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]

所以以下是允许的:

for x in 1, 2, 3:
    print(x)

【讨论】:

  • +1 这当然解释了为什么for k, in d 有效(因为for k, v in d 有效)。
  • 问题:你应该写for x in 1, 2, 3:还是for x in (1, 2, 3):?我一直都是用第二种方式写的,但那是因为我直到刚才尝试的时候才知道第一种方式是有效的。现在我想知道() 是否是不必要的噪音,或者它们是否有助于阅读代码。 PEP8 是否对此提供任何指导?
  • @ArtOfWarfare PEP8 中没有具体的指导。与if 语句进行比较可能会有所帮助,其中仅建议将括号用于跨越多行的条件。所以:for x in (1, &lt;newline&gt; 2, &lt;newline&gt; 3):.
【解决方案2】:

你可以在任何地方使用expression_list这个词,你不需要使用括号。

if statement 需要expression,不支持expression_list

允许expression_list 的语法示例:

expression_listExpressionsSimpleCompound statements 文档中查找expression_list 将告诉您在Python 语法中使用expression_list 的所有位置。

【讨论】:

  • 哦,是吗? 1,2,3 + 4,5 怎么样?它不会产生您可能期望的表达式列表...
  • @smci 这与我的回答有什么关系?你期待什么结果?
  • 因为1,2,3 + 4,5 导致表达式1,2,7,5,这不是普通读者所期望的,并且来自于对序列追加重载+
  • @smci 抱歉,但1, 2, 7, 5 正是我所期望的。逗号之间的每一部分都是一个表达式;整体是expression_list。没有对表达式列表求和的语法规则;相反,+ 是包含的表达式之一 (3 + 4) 的一部分。要将两个元组相加,请通过添加括号创建两个单独的表达式。
  • 是的,我知道。但是,非 Python 用户或缺少尾随逗号的人会期望连接元组 1,2,3, + 4,5, 。结尾的逗号有什么不同。
【解决方案3】:

如果您希望避免歧义,也需要使用括号。

以下是两个不同的表达式...仅仅因为某些内容是“表达式列表”,不会导致您可能期望的表达式列表:)

(1, 2, 3) + (4, 5) # results in (1, 2, 3, 4, 5) because + does sequence.extend on the tuples
1, 2, 3 + 4, 5     # this results in (1, 2, 7, 5) because + adds the elements, since there were no parentheses to protect the separate tuples

【讨论】:

  • 1+2+3 * 4+5 相同。当您知道 Python 中的运算符优先级时,结果就非常清楚了。此处不需要使用额外的括号,但对 Python(或数学)中的新手有所帮助。
  • @Jeyekomon: 不,你没有抓住重点:Python operator precedence 不同于 C/C++ operator precedence 不同于 Java operator precedence 等等。这些歧义可能而且确实会导致即使是非常有经验的程序员也会犯错误. Python 不是凭空存在的。每周在 SO 上,您都可以看到(经验丰富的)程序员证明这一点的此类帖子。
猜你喜欢
  • 2012-02-03
  • 2015-11-01
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 2014-01-24
相关资源
最近更新 更多