Python陷阱:简单赋值结束时的逗号逗号

时间:2012-07-23 22:09:16

标签: python

我只花了一天的时间来找到一个错误的逗号引起的错误。寻找我的bug的困难因为第三方回调库加剧了异常而加剧,但它让我想知道为什么Python(2.x)不会引发语法错误而不是创建元组。请考虑以下

>>> a = 1,
>>> a
(1,)

如您所见,尾随逗号创建一个单例元组。这并不违反Python语法(参见http://docs.python.org/reference/expressions.html#grammar-token-expression_list),但它肯定会导致一些意想不到的结果,例如

>>> a == 1,
(False,)

VS

>>> (1,) == a
True

虽然我现在明白发生了什么,但我很困惑为什么Python允许这种语法而不是要求显式括号来创建元组。 在某种情况下,这种行为是必要的,或者至少是有利的吗?在过去的7年里,我几乎完全用Python编程,而且我从来不需要以这种方式创建单例。在大多数方面,Python是一种非常易读和明确的语言。这个特殊的“特征”似乎是非Pythonic。

3 个答案:

答案 0 :(得分:7)

这里是Python的创建者Guido van Rossum,explaining这句语法是如何形成的:

  

向元组添加类似数组的接口的一个结果就是我   必须找出一些方法来解决元组的边缘情况   长度为0或1.我从ABC获取的规则之一是每个数据   类型,当打印或转换为字符串时,应表示为   表达式,是语言解析器的有效输入。所以   接下来我需要有0和1长度元组的符号。   同时我不想失去a之间的区别   一元组和一个简单的括号表达式,所以我选择了一个   丑陋但务实的方法,一个尾随的逗号会变成一个   表达成一元组和"()"将代表一个零元组。   通常不需要括号,这是值得的   Python的元组语法,除了这里 - 我觉得代表空   “没有”的元组太容易掩盖真正的拼写错误。

另见TupleSyntax上的这个PythonInfo Wiki,特别是" ...定义元组"的是逗号,而不是括号。

虽然这种语法并不美观(Guido说丑陋但又务实),但我认为这不是一个问题。真正的问题是,你的第三方图书馆是"诱捕异常"从而隐藏有关错误的重要信息。

答案 1 :(得分:2)

有一个例子,它可以派上用场,交换两个值。当然你可以在这里使用明确的括号,但没有它们看起来会更好。

a, b = b, a

答案 2 :(得分:2)

抱歉,我没有足够的代表发表评论,所以这就是它自己的答案。

这里有两个相关但不同的东西 - 元组解包并只创建一个元组文字。

在Mark Ransom的回答中找到了元组拆包。

元组虽然似乎是人们的绊脚石。它们不是用括号创建的,括号仅用于消除歧义。逗号定义了一个元组,因此a,是一个带有一个元素的元组,因为,这就是一个元组,一个带逗号的东西:)。 (需要注意的是,对于空元组,而不是看起来很丑的,,我们会遇到(),这可能是人们似乎对此有困难的根源。)