我花了大约一天的时间在一个赋值语句的末尾找到一个由逗号逗号引起的错误.寻找我的bug的困难因为第三方回调库加剧了异常而加剧,但它让我想知道为什么Python(2.x)不会引发语法错误而不是创建元组.考虑以下
>>> a = 1,
>>> a
(1,)
Run Code Online (Sandbox Code Playgroud)
如您所见,尾随逗号创建一个单例元组.这不违反Python语法(参见http://docs.python.org/reference/expressions.html#grammar-token-expression_list),但它肯定会导致一些意想不到的结果,例如
>>> a == 1,
(False,)
Run Code Online (Sandbox Code Playgroud)
VS
>>> (1,) == a
True
Run Code Online (Sandbox Code Playgroud)
虽然我现在明白发生了什么,但我很困惑为什么Python允许这种语法而不是要求显式括号来创建元组.是否存在某种情况需要这种行为,或者至少是有利的? 在过去的7年里,我几乎完全使用Python进行编程,而且我从来不需要以这种方式创建单例.在大多数方面,Python是一种非常易读和明确的语言.这个特殊的"特征"似乎是非Pythonic.
这是Python的创建者Guido van Rossum,解释了这种语法是如何形成的:
向元组添加类似数组的接口的一个结果是我必须找到一些方法来解决长度为0或1的元组的边缘情况.我从ABC中获取的一个规则是每种数据类型,当打印或转换为字符串,应该由表达式表示,该表达式是语言解析器的有效输入.因此,我需要有0和1长度元组的符号.与此同时,我不想失去一元组和一个带括号的表达式之间的区别,所以我选择了一种丑陋但实用的方法,其中一个尾随的逗号会将表达式转换为一元组并且"() "将代表一个零元组.Python的元组语法通常不需要括号,除了这里 - 我觉得通过"无"代表空元组可能太容易掩盖真正的拼写错误.
另请参阅TupleSyntax上的这个PythonInfo Wiki ,特别是"...它是逗号,而不是括号,用于定义元组".
虽然这种语法并不美观(Guido说丑陋但又务实),但我认为这并不是什么问题.真正的问题是你的第三方库是"捕获异常",因此隐藏了有关错误的重要信息.