1

我刚刚花了一天的大部分时间来寻找一个由赋值语句末尾的杂散逗号引起的错误。捕获异常的第三方回调库加剧了查找错误的难度,但这让我想知道为什么 Python (2.x) 不会引发语法错误而不是创建元组。考虑以下

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

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

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

对比

>>> (1,) == a
True

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

4

3 回答 3

7

这是 Python 的创建者 Guido van Rossum,解释了这种语法是如何形成的:

向元组添加类似数组的接口的一个结果是,我必须想办法解决长度为 0 或 1 的元组的边缘情况。我从 ABC 中得到的规则之一是,每种数据类型在打印或转换为字符串,应由作为语言解析器的有效输入的表达式表示。因此,我需要为 0 和 1 长度的元组提供符号。同时我不想失去单元组和带括号的表达式之间的区别,所以我选择了一种丑陋但实用的方法,尾随的逗号会将表达式变成单元组和 "() " 将代表一个零元组。Python的元组语法通常不需要括号,这毫无价值,

另请参阅TupleSyntax上的 PythonInfo Wiki ,尤其是“......定义元组的是逗号,而不是括号”。

虽然这种语法并不漂亮(Guido 说丑,但很实用),但我不认为这是一个陷阱。真正的问题是您的第三方库正在“捕获异常”,从而隐藏了有关您的错误的重要信息。

于 2012-07-23T23:16:28.397 回答
2

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

a, b = b, a
于 2012-07-23T22:16:55.930 回答
2

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

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

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

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

于 2012-07-23T22:52:34.850 回答