逗号运算符优先级

时间:2019-09-10 20:05:51

标签: python

找不到记录/解释此内容的统一资源。我很困惑;是运营商吗?最重要的是,它的优先顺序是什么?一个例子:

import functools
def array_sum(array):
    return functools.reduce(lambda acc, curr: acc + curr, array)
print(array_sum([1,2])) # 3
# https://docs.python.org/3/reference/expressions.html#operator-precedence tells us that lambda has the lowest precedence.
# But the above code works, which means the comma gets applied after the lambda expression.
# If the comma was applied first, that would give us this runtime error: TypeError: reduce expected at least 2 arguments, got 1

请注意,在代码注释的链接中甚至没有将逗号列为运算符。但是这里它被称为运算符:https://docs.python.org/3/reference/expressions.html#parenthesized-forms

Python版本:3.7.4


编辑:

我最初提供的是另一个但不正确的示例:

x = 4 if False else 3, 2
print(x) # (3,2)
x = 4 if True else 3, 2
print(x) # 4
# comma was applied before assignment operator

x, y = 4 if True else 3, 2
print(x) # 4
print(y) # 2
# comma was applied after assignment operator

但这是我的错误,因为

x = 4 if True else 3, 2
print(x) # 4

不正确,再次运行后,我看到纠正后是:

x = 4 if True else 3, 2
print(x) # (4, 2)

因此,在编辑中删除的示例中,逗号优先顺序始终保持一致。

3 个答案:

答案 0 :(得分:3)

右侧:

4 if False else 3, 2
首先评估

,并且可以将其可视化为((4 if False else 3), 2),这是一个隐式元组(没有()的元组,但是仍然是元组),最终将是3, 2或{ {1}}(取决于对4, 2条件的评估),然后根据左侧的内容进行赋值,因此,由于{{ 1}},if将是一个元组(x = 4 if False else 3, 2x),但是如果您像(3, 2)那样使用拆包,则分配为:

(4, 2)

答案 1 :(得分:3)

Assignment Statements的文档对分配给单个目标或多个目标进行了区分。

  

如果目标列表是没有尾随逗号的单个目标,则可以选择将其分配给该目标。

因此,在第一种情况下,分配的RHS(在文档中称为“对象”)被解析为单个对象。逗号被解析为条件表达式的else子句的值。

  

其他:对象必须是可迭代的,并且具有与目标列表中的目标相同数量的项目,并且这些项目从左到右分配给相应的目标。

因此,在这种情况下,它首先尝试将RHS解析为具有两个项目的可迭代表达式。逗号被视为生成器表达式中各项之间的分隔符。

答案 2 :(得分:2)

在两种情况下,RHS都被解析为元组,可以通过打印生成的AST来查看。

区别在于,第二种情况下打开包装,而第一种情况下没有打开包装

>>> from astpretty import pprint as pp
>>> import ast
>>> a = ast.parse('x = 1 if True else 2, 3')
>>> pp(a)
Module(
    body=[
        Assign(
            lineno=1,
            col_offset=0,
            targets=[Name(lineno=1, col_offset=0, id='x', ctx=Store())],
            value=Tuple(
                lineno=1,
                col_offset=4,
                elts=[
                    IfExp(
                        lineno=1,
                        col_offset=4,
                        test=NameConstant(lineno=1, col_offset=9, value=True),
                        body=Num(lineno=1, col_offset=4, n=1),
                        orelse=Num(lineno=1, col_offset=19, n=2),
                    ),
                    Num(lineno=1, col_offset=22, n=3),
                ],
                ctx=Load(),
            ),
        ),
    ],
)
>>> b = ast.parse('x, y = 4 if True else 3, 2')
>>> pp(b)
Module(
    body=[
        Assign(
            lineno=1,
            col_offset=0,
            targets=[
                Tuple(
                    lineno=1,
                    col_offset=0,
                    elts=[
                        Name(lineno=1, col_offset=0, id='x', ctx=Store()),
                        Name(lineno=1, col_offset=3, id='y', ctx=Store()),
                    ],
                    ctx=Store(),
                ),
            ],
            value=Tuple(
                lineno=1,
                col_offset=7,
                elts=[
                    IfExp(
                        lineno=1,
                        col_offset=7,
                        test=NameConstant(lineno=1, col_offset=12, value=True),
                        body=Num(lineno=1, col_offset=7, n=4),
                        orelse=Num(lineno=1, col_offset=22, n=3),
                    ),
                    Num(lineno=1, col_offset=25, n=2),
                ],
                ctx=Load(),
            ),
        ),
    ],
)

涉及到此的文档有点难以跟踪。首先在这里找到赋值表达式 https://docs.python.org/3.7/reference/simple_stmts.html#assignment-statements

RHS部分是一个starred_expression,它指向https://docs.python.org/3.7/reference/expressions.html#expression-lists

  

除了列表或集合显示的一部分外,表达式列表   包含至少一个逗号会产生一个元组。元组的长度   是列表中表达式的数量。表达式是   从左到右评估。

在这里记笔记:

  

包含至少一个逗号会产生一个元组

这是您的答案。 RHS中任何带有逗号(不是列表或集合)的元素都将产生元组

我希望对您有帮助