Python:是否有语法级支持解压缩,从元组,到*anonymous*函数的参数?

ste*_*red 3 python lambda coding-style language-design iterable-unpacking

假设我们有以下内容:

args = (4,7,5)
def foo(a,b,c): return a*b%c
Run Code Online (Sandbox Code Playgroud)

Python方便地允许元组解包:

foo(4,7,5)             # returns 3
foo(*args)             # returns foo(4,7,5), i.e. 3
Run Code Online (Sandbox Code Playgroud)

所以我们不必这样做:

foo(t[0], t[1], t[2])  # a repulsive, verbose, and error-prone synonym
Run Code Online (Sandbox Code Playgroud)

现在假设我们有一个类似的3元组列表,并希望列出foo(t)每个元组的列表t.有"一种明显的方法":

list(map(lambda t: foo(*t), listoftuples))
Run Code Online (Sandbox Code Playgroud)

但现在假设foo只是一个扔掉的功能.我们不希望垃圾污染我们的命名空间.让我们在匿名的地毯下扫一扫!:

list(map(lambda t: (lambda a, b, c: a*b%c)(*t), listoftuples))
Run Code Online (Sandbox Code Playgroud)

好吧,我们现在有嵌套的lambda.当然,我们可以解析它.但是我们冒着被误认为是一个阴谋家的风险,这个阴谋家喜欢构造神秘的法术,其唯一目的就是为那些冒昧的人重新审视我们的代码.

此外,对于这样一个简单的想法,这有点冗长.这似乎不是pythonic.(在scala中,相当于内部lambda (_*_%_),假设上下文允许类型推断.如果这 pythonic,它不会同样简洁吗?).

我们可以这样删除内部lambda:

list(map((lambda t: t[0] * t[1] % t[2]), listoftuples))
Run Code Online (Sandbox Code Playgroud)

那更短,但令人厌恶.我发现使用幻数(而不是名称)来引用参数往往会导致错误.

如果它看起来更像这样会很棒:

list(map((lambda a, b, c: a*b%c), listoftuples))
Run Code Online (Sandbox Code Playgroud)

当然,它不可能.这就像打电话一样foo(args).我们需要一个星号,可以这么说.这是一个可能的星号:

def unpackInto(func): return lambda t: func(*t)
Run Code Online (Sandbox Code Playgroud)

它使代码具有令人愉悦的可读性:

list(map(unpackInto(lambda a, b, c: a*b%c), listoftuples))
Run Code Online (Sandbox Code Playgroud)

但是我们必须始终从个人模块中导入它.这不适合协作,对于一次性使用来说有点烦人.

TL; DR

我想unpackInto成为这门语言的一部分.它是否已在语法中受支持?在标准库中?

Bak*_*riu 5

在python2它可以使用元组拆包此:

>>> def func((a,b,c)):
...     return a+b+c
... 
>>> func((1,2,3))
6
Run Code Online (Sandbox Code Playgroud)

但是在python3 中删除了此功能.见PEP 3113.它被删除的原因是:

  • 他们很难反省
  • 它们不会引入任何功能,因为您可以创建如下函数:

    def func(a_b_c):
       a,b,c = a_b_c
    
    Run Code Online (Sandbox Code Playgroud)

    并取得同样的结果

  • 他们提供了丑陋的错误消息

有了这个去除蟒蛇目前并不能支持你希望与任何语法,也没有任何STDLIB功能是什么.

由于这个语法是用PEP删除的,我非常怀疑核心开发人员会接受你的unpack_into功能.然而,可能有一个很小的机会将类似的东西添加到functools应该包含这种东西的模块中.你应该向python开发人员询问这个问题,但一定要提供好的参数来支持你的请求.


ste*_*red 5

starmap它在 itertools 包中

从我的例子:

list(map(lambda t: foo(*t), listoftuples))
Run Code Online (Sandbox Code Playgroud)

变成

list(starmap(foo, listoftuples))
Run Code Online (Sandbox Code Playgroud)

明白为什么它被称为星图了吗?并使用匿名函数:

def unpackInto(func): return lambda t: func(*t)
list(map(unpackInto(lambda a, b, c: a*b%c), listoftuples))
Run Code Online (Sandbox Code Playgroud)

变成

list(starmap(lambda a, b, c: a*b%c, listoftuples))
Run Code Online (Sandbox Code Playgroud)

一个简单的四字母前缀,star是我正在寻找的“星号”。

所以,是的,有标准库支持将元组中的参数解包到匿名函数中,仅适用于 map,通过 starmap。

没有,没有语法层面的支持,在Python 2.见Bakuriu的答案语法层面的支持。最后会变成:

list(map(lambda (a, b, c): a*b%c, listoftuples))
Run Code Online (Sandbox Code Playgroud)

哪个更简洁。它不得不被带走几乎是一种耻辱。

再说一次,lambda 很少像列表推导那样简洁或易读:

[a*b%c for a, b, c in listoftuples]
Run Code Online (Sandbox Code Playgroud)