繁体   English   中英

是否有内置的“ apply”函数(如“ lambda f:f()”),就像Python 2中那样?

[英]Is there a built-in “apply” function (like “lambda f: f()”) as there used to be in Python 2?

看着这个问题 ,我意识到,如果要并行运行一系列函数,使用multiprocessingPool.map有点尴尬:

from multiprocessing import Pool

def my_fun1(): return 1
def my_fun2(): return 2
def my_fun3(): return 3

with Pool(3) as p:
   one, two, three = p.map(lambda f: f(), [my_fun1, my_fun2, my_fun3])

我并不是说这是完全神秘的,但我想我希望为此使用一些常规名称,即使仅在functools东西中,也类似地在JavaScript中apply / call (是的,我知道JavaScript当时没有lambdas这些功能已定义,不,我不是说JavaScript是一种示例性编程语言,仅是示例)。 实际上,我绝对认为operator应该存在类似的内容,但是(除非我的眼睛蒙蔽了我)它似乎不存在。 我读到, 对于身份函数 ,解决方案是让人们定义自己的琐碎函数,在这种情况下,我会更好地理解它,因为您可能需要几个不同的变体,但是这种感觉就像是缺少了一点对我来说。

编辑:正如评论中指出的那样,Python 2曾经有一个为此目的apply功能。

首先,让我们看一下实际问题。

对于任何的Python 2.3,你可以平凡写不只是你不带参数的apply ,而是一个完美转发apply ,作为一个班轮,如解释在2.x文档的apply

apply()的使用等效于function(*args, **keywords)

换一种说法:

def apply(function, *args, **keywords):
    return function(*args, **keywords)

…或者作为内联lambda:

lambda f, *a, **k: f(*a, **kw)

当然,C语言的实现要快一些,但这几乎没有关系。 1

如果您打算不止一次使用此功能,我认为可以离线定义函数并按名称重用它,但lamdba版本很简单也很明显(对于您的无参数来说更是如此)用例),我无法想象有人对此抱怨。

另外,请注意,如果您了解自己在做什么,那实际上比identity更琐碎,而不是更少。 对于identity ,应返回带有多个参数(或关键字参数)的内容是不明确的,因此您必须确定所需的行为。 对于apple ,只有一个明显的答案,而且几乎不可能出错。


至于历史:

像JavaScript一样,Python最初没有lambda 很难找到2.6之前的版本的可链接文档,甚至很难找到2.3之前的版本,但是我认为lambda是在1.5中添加的,最终达到可以在2.2左右完美转发的程度。 在此之前,文档建议使用apply进行转发,但在此之后,文档建议使用lambda代替apply 实际上,不再建议使用apply

因此在2.3中,该功能已被弃用。 2

在Python的3000的讨论,导致3.0,圭多建议所有的“函数式编程”的功能除了可能 mapfilter是不必要的。 3其他人为reducepartial提出了很好的partial 4但是,这种情况的很大一部分是,它们实际上并不容易编写(以完全通用的形式),而且容易出错。 apply并非如此。 而且,人们能够在现实世界的代码库中找到化reducepartial相关用法,但任何人都可以找到的apply的唯一用法是2.3之前的旧代码。 实际上,这种情况很少见,甚至不值得进行2to3工具转换调用apply

PEP 3100总结了删除它的最终原理:

apply() :改用f(*args, **kw) [2]

该脚注链接到Guido的文章“ Python Regrets”,该文章现在是404链接。 随附的PowerPoint演示文稿仍然可用 ,或者,您也可以查看他为其编写的演示文稿的HTML活页簿 但是它真正说的是同一行,而IIRC,唯一进一步的讨论是“我们已经在2.3中有效地摆脱了它”。


1.在大多数必须应用函数的惯用Python代码中,该函数内部的工作非常繁重。 当然,在您的情况下,调用函数(分配参数并将其通过管道传递)的开销甚至更大。 一种重要的情况是,当您执行“ Haskell风格的函数式编程”而不是“ Lisp风格”时,也就是说,很少的函数定义,并且通过转换函数和组合结果来创建许多函数。 但这在Python中已经太慢了(而且栈很重),所以这不是一件合理的事情。 (平整地使用装饰器来应用一个或三个包装器效果很好,但是可能无限制的包装器链会影响您的性能。)

2.正式的弃用机制尚不存在,因此仅移至文档中的“非必需的内置函数”部分。 但是从2.3版本开始,追溯地认为它已被弃用,正如您在2.7文档中所见。

3. Guido最初甚至想摆脱它们; 争论在于列表理解可以更好地完成相同的工作,正如您在“遗憾”翻书中所见。 但是,将itertools.imap替换为map意味着可以像新的zip一样使它变懒,因此比理解更好。 我不确定Guido为什么不只使用生成器表达式来做相同的参数。

4.我不确定Guido自己是否曾经说服过reduce ,但是整个核心开发人员都是。

如果您要做一行额外的工作,它就在operator

>>> def foo():
...     print 'hi'
... 
>>> from operator import methodcaller
>>> call = methodcaller('__call__')
>>> call(foo)
hi

当然, call = lambda f: f()也只是一行而已...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM