【问题标题】:Where does python argument unpacking fall into the order of operations?python参数解包在哪里属于操作顺序?
【发布时间】:2013-10-22 18:26:09
【问题描述】:

http://docs.python.org/2/reference/expressions.html#operator-precedence

我的猜测是它属于 dict 查找之上的桶之一,因为

func(*mydict[mykey])

首先进行字典查找。 有没有比我最初的链接更好的图表来更详细地介绍 python 中的操作顺序?

【问题讨论】:

  • 这不是一个操作,它是函数调用的一部分。 *mydict[mykey] 本身没有任何意义,只有 func(*mydict[mykey]) 会导致参数解包。
  • 请注意,在 Python 3 中,元组解包不再是函数调用的一部分(这就是 a, *b = (1, 2, 3) 起作用的原因),并且整个事情都得到了更好的解释……但这对 Python 2 没有帮助。(此外,即使在 3.x 中,也不清楚解包 * 到底是什么。在某些地方它被称为运算符,并明确表示在其他……)
  • @abarnert 在 Python 3 中,元组解包 函数调用的一部分。唯一改变的是它现在是作业的一部分。

标签: python


【解决方案1】:

解包*不是运算符;它是调用语法的一部分。它在Calls 下定义,您可以在其中看到:

["," "*" expression]

…可以在两个不同的地方成为argument_list 的一部分。 (语义在“如果有更多位置…”和“如果语法…”开头的段落中描述。)

所以它需要任何expression。您可以看到没有运算符将完整的expression 作为其直接参数。因此,如果您想松散地考虑 * 一个运算符,它的绑定比任何运算符都松散。但请记住,它实际上并不是一个运算符。

还请记住,这在 Python 3.x 中已全部更改。但基本思想是相同的——参数解包和赋值解包都采用expression,而不仅仅是primary,因此松散地说绑定比任何运算符都更松散,它们都采用primary或更具体的东西.


同时,您可能想尝试在您的代码上运行解析器,看看它做了什么:

>>> import ast
>>> tree = ast.parse('func(*mydict[mykey])')
>>> ast.dump(tree)
"Module(body=[Expr(value=Call(func=Name(id='func', ctx=Load()), args=[], keywords=[],
starargs=Subscript(value=Name(id='mydict', ctx=Load()),
slice=Index(value=Name(id='mykey', ctx=Load())), ctx=Load()), kwargs=None))])"

您可以看到整个Subscript 表达式以starargsCall 结尾。

ast 模块使用Abstract Grammar 而不是参考手册中描述的那个。它对事物有不同的名称,并且不处理一些被认为是语法的一部分但实际上在比解析器更高的级别上完成的事情,等等——但另一方面,它更容易接受一次全部。您可以看到用于starargsexpr 可以是Subscript

【讨论】:

  • 我看不出这个“在 Python 3 中是如何改变的”。调用的语法几乎相同,尤其是在解包本身的行为方面。
  • @poke:调用starargs和赋值目标的语法是统一的(以及def varargs)。我想这并没有太大的实际区别。无论哪种方式,松散的答案是“如果您将其视为运算符,它的优先级低于任何运算符”,而正确的答案包括阅读参考语法或抽象语法或使用ast 为您做后者……
  • 你的观点没有实际意义。在 Python 2 和 Python 3 中,代码产生 相同的 AST,所以这些小的语法变化在这里并没有真正的影响,而且绝对不意味着它“在 Python 3 中都发生了变化” ——这意味着一种完全不同的行为,尽管这根本不是真的……
【解决方案2】:

正如 BrenBarn 在 cmets 中提到的,解包被定义为 function calls(Python 2 和 3)和 assignment statements(Python 3)的一部分。

所以不,它永远不会占据运算符优先级的一部分,因为它不是运算符。

我怎么知道在这个例子中这不会尝试解压“mydict”?或者这是语言解析器处理的东西。

在您的示例func(*mydict[mykey]) 中,函数调用的规范适用。所以让我们尝试手动解析

基础部分与call的定义相匹配,所以*mydict[mykey]就是argument_list。而在参数列表中,它将被解析为"*" expressionmydict[mykey] 是表达式。因此,解析器永远不会首先应用解包,因为语法根本没有指定在 "*" expression 之后的括号中的另一部分的情况。

【讨论】:

  • 啊,我明白了,所以在计算表达式之后进行解包。
  • 此答案适用于 Python 3。Python 2 中的情况并没有巨大不同,但它们是不同的。您可以使用文档页面顶部的版本下拉菜单切换到您的特定版本。
猜你喜欢
  • 2016-09-19
  • 1970-01-01
  • 2010-10-08
  • 2010-11-07
  • 2020-03-16
  • 2015-08-20
  • 2020-10-08
  • 2016-12-08
相关资源
最近更新 更多