是否有内置的 "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?
查看 this question, I realised that it is kind of awkward to use multiprocessing
's Pool.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
or something, similarly to apply
/call
in JavaScript (yes, I know JavaScript didn't have lambdas at the time those functions were defined, and no, I'm not saying JavaScript is an exemplary programming language, just an example). In fact, I definitely think something like this should be present in operator
, but (unless my eyes deceive me) it seems to be absent. I read that in the case of the identity function 内解决方案是让人们定义他们自己的琐碎函数,我理解在那种情况下更好,因为您可能需要几个不同的变体,但我觉得这个变体有点缺失。
编辑:正如评论中所指出的,Python 2 曾经有一个用于此目的的 apply
函数。
如果你做一行额外的工作,它有点在 operator
中:
>>> def foo():
... print 'hi'
...
>>> from operator import methodcaller
>>> call = methodcaller('__call__')
>>> call(foo)
hi
当然,call = lambda f: f()
也只是一行...
首先,我们来看实际问题。
对于从 2.3 开始的任何 Python,您不仅可以简单地编写 no-argument apply
,还可以编写 perfect-forwarding apply
,作为 one-liner,如 the 2.x docs for apply
:
中所述
The use of apply()
is equivalent to function(*args, **keywords)
换句话说:
def apply(function, *args, **keywords):
return function(*args, **keywords)
... 或者,作为内联 lambda:
lambda f, *a, **k: f(*a, **kw)
当然 C 实现要快一点,但这几乎无关紧要。1
如果你要多次使用它,我认为定义函数 out-of-line 并按名称重用它可能更清楚,但 lamdba 版本足够简单明了(更是如此对于您的 no-args 用例),我无法想象有人会抱怨它。
此外,请注意,如果您了解自己在做什么,这实际上比 identity
更简单,而不是更少。使用 identity
,你应该 return 有多个参数(或关键字参数)是不明确的,所以你必须决定你想要哪种行为;对于 apple
,只有一个明显的答案,而且几乎不可能出错。
至于历史:
Python,和JavaScript一样,本来就没有lambda
。 2.6 之前的版本很难找到 linkable 文档,2.3 之前的版本也很难找到,但我认为 lambda
是在 1.5 中添加的,最终达到了可以用于的地步2.2左右的完美转发。在此之前,文档建议使用apply
进行转发,但在此之后,文档建议使用lambda
代替apply
。事实上,不再推荐使用 apply
.
因此在 2.3 中,该函数已被弃用。2
在导致 3.0 的 Python-3000 次讨论中,Guido 建议所有 "functional programming" 函数除了 maybe map
和filter
是不必要的。3 其他人为 reduce
和 partial
做了很好的案例。4 但是一个大部分原因是它们实际上写起来并不简单(以 fully-general 形式),而且很容易出错。 apply
并非如此。此外,人们能够在 real-world 代码库中找到 reduce
和 partial
的相关用途,但任何人都能找到的 apply
的唯一用途是旧的 pre-2.3 代码。事实上,这种情况非常罕见,甚至不值得对 apply
.
进行 2to3
工具转换调用
删除它的最终理由总结在 PEP 3100 中:
apply()
: use f(*args, **kw)
instead [2]
Guido 的一篇名为 "Python Regrets" 的文章的脚注 link,现在是 404 link。随附的 PowerPoint 演示文稿是他为其编写的演示文稿的 still available, however, or you can view an HTML flipbook。但它真正说的都是一样的 one-liner 和 IIRC,唯一进一步的讨论是 "We already effectively got rid of it in 2.3."
1.在大多数必须应用函数的惯用 Python 代码中,该函数内部的工作非常繁重。当然,在您的情况下,调用函数的开销(腌制参数并通过管道传递它们)甚至更重。重要的一种情况是当您执行 "Haskell-style functional programming" 而不是 "Lisp-style" 时——也就是说,函数定义非常少,而许多函数是通过转换函数和组合结果生成的。但这在 Python 中已经很慢了(并且 stack-heavy),这不是一件合理的事情。 (平面使用装饰器来应用一个或三个包装器效果很好,但潜在的无限包装器链会降低您的性能。)
2。正式的弃用机制还不存在,所以它只是被移动到文档中的 "Non-essential Built-in Functions" 部分。但它被追溯认为自 2.3 以来已弃用,如您在 2.7 文档中所见。
3。圭多原本连他们也想除掉;正如您在 "Regrets" 活页簿中看到的那样,争论的焦点是列表理解可以更好地完成同样的工作。但是提升 itertools.imap
代替 map
意味着它可以像新的 zip
一样变得懒惰,因此比理解更好。我不确定为什么 Guido 不只是对生成器表达式提出相同的论点。
4.我不确定 Guido 本人是否曾相信 reduce
,但整个核心开发人员都相信。
查看 this question, I realised that it is kind of awkward to use multiprocessing
's Pool.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
or something, similarly to apply
/call
in JavaScript (yes, I know JavaScript didn't have lambdas at the time those functions were defined, and no, I'm not saying JavaScript is an exemplary programming language, just an example). In fact, I definitely think something like this should be present in operator
, but (unless my eyes deceive me) it seems to be absent. I read that in the case of the identity function 内解决方案是让人们定义他们自己的琐碎函数,我理解在那种情况下更好,因为您可能需要几个不同的变体,但我觉得这个变体有点缺失。
编辑:正如评论中所指出的,Python 2 曾经有一个用于此目的的 apply
函数。
如果你做一行额外的工作,它有点在 operator
中:
>>> def foo():
... print 'hi'
...
>>> from operator import methodcaller
>>> call = methodcaller('__call__')
>>> call(foo)
hi
当然,call = lambda f: f()
也只是一行...
首先,我们来看实际问题。
对于从 2.3 开始的任何 Python,您不仅可以简单地编写 no-argument apply
,还可以编写 perfect-forwarding apply
,作为 one-liner,如 the 2.x docs for apply
:
The use of
apply()
is equivalent tofunction(*args, **keywords)
换句话说:
def apply(function, *args, **keywords):
return function(*args, **keywords)
... 或者,作为内联 lambda:
lambda f, *a, **k: f(*a, **kw)
当然 C 实现要快一点,但这几乎无关紧要。1
如果你要多次使用它,我认为定义函数 out-of-line 并按名称重用它可能更清楚,但 lamdba 版本足够简单明了(更是如此对于您的 no-args 用例),我无法想象有人会抱怨它。
此外,请注意,如果您了解自己在做什么,这实际上比 identity
更简单,而不是更少。使用 identity
,你应该 return 有多个参数(或关键字参数)是不明确的,所以你必须决定你想要哪种行为;对于 apple
,只有一个明显的答案,而且几乎不可能出错。
至于历史:
Python,和JavaScript一样,本来就没有lambda
。 2.6 之前的版本很难找到 linkable 文档,2.3 之前的版本也很难找到,但我认为 lambda
是在 1.5 中添加的,最终达到了可以用于的地步2.2左右的完美转发。在此之前,文档建议使用apply
进行转发,但在此之后,文档建议使用lambda
代替apply
。事实上,不再推荐使用 apply
.
因此在 2.3 中,该函数已被弃用。2
在导致 3.0 的 Python-3000 次讨论中,Guido 建议所有 "functional programming" 函数除了 maybe map
和filter
是不必要的。3 其他人为 reduce
和 partial
做了很好的案例。4 但是一个大部分原因是它们实际上写起来并不简单(以 fully-general 形式),而且很容易出错。 apply
并非如此。此外,人们能够在 real-world 代码库中找到 reduce
和 partial
的相关用途,但任何人都能找到的 apply
的唯一用途是旧的 pre-2.3 代码。事实上,这种情况非常罕见,甚至不值得对 apply
.
2to3
工具转换调用
删除它的最终理由总结在 PEP 3100 中:
apply()
: usef(*args, **kw)
instead [2]
Guido 的一篇名为 "Python Regrets" 的文章的脚注 link,现在是 404 link。随附的 PowerPoint 演示文稿是他为其编写的演示文稿的 still available, however, or you can view an HTML flipbook。但它真正说的都是一样的 one-liner 和 IIRC,唯一进一步的讨论是 "We already effectively got rid of it in 2.3."
1.在大多数必须应用函数的惯用 Python 代码中,该函数内部的工作非常繁重。当然,在您的情况下,调用函数的开销(腌制参数并通过管道传递它们)甚至更重。重要的一种情况是当您执行 "Haskell-style functional programming" 而不是 "Lisp-style" 时——也就是说,函数定义非常少,而许多函数是通过转换函数和组合结果生成的。但这在 Python 中已经很慢了(并且 stack-heavy),这不是一件合理的事情。 (平面使用装饰器来应用一个或三个包装器效果很好,但潜在的无限包装器链会降低您的性能。)
2。正式的弃用机制还不存在,所以它只是被移动到文档中的 "Non-essential Built-in Functions" 部分。但它被追溯认为自 2.3 以来已弃用,如您在 2.7 文档中所见。
3。圭多原本连他们也想除掉;正如您在 "Regrets" 活页簿中看到的那样,争论的焦点是列表理解可以更好地完成同样的工作。但是提升 itertools.imap
代替 map
意味着它可以像新的 zip
一样变得懒惰,因此比理解更好。我不确定为什么 Guido 不只是对生成器表达式提出相同的论点。
4.我不确定 Guido 本人是否曾相信 reduce
,但整个核心开发人员都相信。