函数调用中的Python理解(PEP 448)

时间:2016-08-20 00:41:27

标签: python python-3.x language-lawyer

(这完全在Python 3.5.2上)

PEP 448的底部,我看到了:

  

函数调用中未括号的理解(例如f(x for x in it))已经有效。

这很有趣。如果我定义以下函数:

def f(a, b, c):
    return a + b + c
然后那句话让我想到f(thing for thing in [1, 2, 3]) == 6。但实际上,我得到了:

>>> f(thing for thing in [1, 2, 3])
TypeError: f() missing 2 required positional arguments: 'b' and 'c'

即。整个生成器表达式传递为a

那么PEP 448中的这句话是什么意思?只是你可以将生成器表达式作为参数传递?

4 个答案:

答案 0 :(得分:4)

此声明仅表示在 pre-PEP 世界f(x for x in it)中已经有效并将生成器表达式作为第一个函数参数传递。

要使您的示例正常工作,您需要显式解包生成器,如PEP示例中所示。

f(*(thing for thing in [1, 2, 3]))  # returns 6

答案 1 :(得分:1)

Python允许您将单个生成器表达式传递给您正在调用的函数,而无需额外的括号。例如:

foo(x for x in range(10))

大致相当于:

genexp = (x for x in range(10)) # parentheses are necessary here
foo(genexp)

如果还有其他参数传递给函数调用(例如foo(w, (x for x in range(10)), y, z),那么在定义生成器表达式时仍然需要括号(其中第二个参数是{{1}的生成器表达式}}' S)

PEP顺便提一下,在这种情况下,解包语法的进一步扩展可能会令人困惑。如果一种新的生成器表达式x是合法的(它不是最终的PEP的一部分,但正在考虑一段时间),那么(*x for x in nested)应该如何工作?它是否等同于foo(*x for x in nested)(使用单个生成器表达式调用,包括新的"展平" foo((*x for x in nested))),或者它是否意味着*(这是合法的)现在)?

答案 2 :(得分:0)

发生的事情是,在f(thing for thing in [1, 2, 3])行,您只传递第一个参数,即一个生成器。缺少参数bc

另外,请检查PEP的以下部分:

  

但是,目前尚不清楚这是最好的行为还是它   应解压缩到f调用的参数中。既然如此   这可能是令人困惑的,并且只是非常边际的效用,事实并非如此   包含在本PEP中。相反,这些将抛出一个SyntaxError和   应该使用带有明确括号的理解。

答案 3 :(得分:0)

实际上f(x for x in it)不是由PEP 448引入的新功能,而是由PEP 289引入的。注意到并非PEP 448中讨论的所有功能都在Python 3.5中实现。问题中提到的"Variations" section未实施:

  

因为这可能令人困惑,而且只是非常微不足道   实用程序,它不包含在本PEP中。相反,这些将抛出一个   应使用SyntaxError和带有明确括号的理解   代替。