Python的一个陷阱:简单赋值末尾有一个逗号



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

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

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

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

>>> (1,) == a
True

虽然我现在明白了发生了什么,但我对Python为什么允许这种语法而不需要显式括号来创建元组感到困惑在某些情况下,这种行为是必要的,或者至少是有利的吗在过去的7年里,我几乎完全用Python进行编程,从未需要用这种方式创建单例。在大多数方面,Python都是一种可读性极佳且明确的语言。这个特殊的"特性"看起来,嗯,不是Python的。

下面是Python的创建者Guido van Rossum,他解释了这一语法是如何产生的:

向元组添加类似数组的接口的一个结果是必须找到一些方法来解决元组的边缘情况长度0或1。我从美国广播公司学到的一条规则是打印或转换为字符串时,类型应表示为作为语言解析器的有效输入的表达式。所以,它然后我需要有0和1长度元组的符号。同时,我不想失去一个元组和一个空括号表达式,所以我选择了丑陋但务实的方法,后面的逗号会变成表达式转换为一元组,"()"表示零元组。括号通常不需要Python的元组语法,除了这里——我觉得表示的是空的元组中的"无"很容易掩盖真正的拼写错误。

另请参阅TupleSyntax上的PythonInfo Wiki,特别是"…定义元组的是逗号,而不是括号"。

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

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

a, b = b, a

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

这里有两件相关但不同的事情——元组拆包和仅仅创建一个元组文本。

在Mark Ransom的回答中可以找到Tuple开箱。

然而,元组似乎是人们的绊脚石。它们不是用括号创建的,括号只用于消除歧义。逗号定义了一个元组,所以a,是一个只有一个元素的元组,因为元组就是这样,一个有逗号的东西:)。(需要注意的是,对于空元组,而不是看起来很难看的,,我们会使用(),这可能是人们在这方面遇到困难的原因。)

最新更新