逗号语法:语句中挂起逗号的基本原理是SyntaxError

时间:2015-05-13 17:50:30

标签: python syntax comma

在Python中,变量或文字后跟悬挂的逗号是一个 - tuple

1, # (1,)

...和一系列以逗号分隔的变量/文字(无论它们是否后跟悬挂的逗号)也是tuple

1,2, # (1,2)
1,2 # (1,2)

但是,在可调用/函数内部,此语法的处理方式不同,因为逗号用于分隔参数:

bool(5>6,) # False - 5>6 == False
bool((5>6,)) # True - (5>6,) is a non-empty tuple (always True - contents ignored)

第一行似乎只是忽略了悬挂的逗号。第二行创建一个 - tuple(如预期的那样)。这也适用于用户定义的函数(不知道它为什么不会):

def f(arg):
    pass
f(1,) # No Error 

还要考虑assert的以下行为(这是一个陈述,而不是一个函数):

assert 5>6 # AssertionError, as expected 
assert(5>6) # AssertionError, as expected 
assert 5>6, # SyntaxError: invalid syntax
assert(5>6,) # SyntaxWarning: assertion always true, perhaps remove parentheses?
assert 5>6, 'NOPE!' # AssertionError: NOPE!, as expected 

因此,我对悬挂逗号处理的解释如下:

  • 如果逗号位于函数参数的上下文中,则忽略它
  • 如果逗号位于语句的上下文中,则表示语法错误
  • 在其他地方,它被解释为tuple对象
  • 的一部分

我的问题:我对上述行为的解释是否正确? Python解释器是否只是忽略在参数列表中找到的悬挂逗号?这种行为是否因Python实现而异?最后:为什么在语句结尾(语法错误)和参数列表末尾(没有语法错误)处理挂起的逗号时会出现不一致的情况?

编辑:在阅读了答案并进一步思考后,我的解释应修改如下:

  • 除了以下两种情况外,悬挂的逗号始终处于忽略状态
  • 如果挂起的逗号位于语句的上下文中,则表示语法错误
  • 如果挂起的逗号表示一个 - tuple

但是,这仍然存在以下问题:为语句提供参数时,不会忽略挂起的逗号,当为函数提供参数时忽略它们。

2 个答案:

答案 0 :(得分:5)

在任何逗号分隔的列表(函数调用,列表/字典文字等)中,尾随逗号始终被忽略。您的.tar示例不是以逗号分隔的列表。

单元组需要尾随逗号的唯一原因是因为没有办法区分单元组和带括号的表达式。

答案 1 :(得分:3)

元组由逗号定义,除非上下文为逗号定义了不同的含义。在这种情况下,您需要使用括号来消除元组逗号和不同逗号的歧义。

assert不是函数,它是一个语句,所以paretheses不是语法的一部分。逗号,所以你需要括号来消除断言表达式和失败消息之间逗号的元组歧义,但你仍然需要用逗号来定义元组。

在定义元组和在调用表达式中使用a时,一致地忽略多余的尾随逗号。但是,您需要了解何时创建元组以及何时使用逗号表示其他表达式。要创建元组,您至少需要一个逗号,而在调用中,您不需要使用该逗号,因为逗号运算符未定义调用语法。

来自Expression lists的文档:

  

包含至少一个逗号的表达式列表会产生一个元组。元组的长度是列表中表达式的数量。表达式从左到右进行评估。

     

仅在创建单个元组时需要尾随逗号(a.k.a. a singleton );在所有其他情况下它都是可选的。没有尾随逗号的单个表达式不会创建元组,而是产生该表达式的值。 (要创建空元组,请使用一对空括号:()。)

Parethesized forms

  

带括号的表单是括在括号中的可选表达式列表:

parenth_form ::=  "(" [expression_list] ")"
     

带括号的表达式列表产生表达式列表产生的任何内容:如果列表包含至少一个逗号,则产生一个元组;否则,它会产生构成表达式列表的单个表达式。

     

一对空括号产生一个空元组对象。由于元组是不可变的,所以文法规则适用(即,两次出现的空元组可能会或可能不会产生相同的对象)。

     

请注意,元组不是由括号组成,而是使用逗号运算符。唯一的例外是空元组,其中括号 是必需的 - 在表达式中允许不带括号的“无”会导致含糊不清并允许常见错别字传递未被捕获。

强调我的。

最后,来自Calls documentation

  

在位置和关键字参数之后可能存在尾随逗号但不影响语义。