Python:为什么需要 functools.partial? [英] Python: Why is functools.partial necessary?

查看:24
本文介绍了Python:为什么需要 functools.partial?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

部分应用很酷.functools.partial 有什么功能提供您无法通过 lambdas 的提议?

<预><代码>>>>总和 = lambda x, y : x + y>>>总和(1, 2)3>>>incr = lambda y : sum(1, y)>>>增量(2)3>>>def sum2(x, y):返回 x + y>>>incr2 = functools.partial(sum2, 1)>>>incr2(4)5

functools 是否更高效或可读?

解决方案

functools.partial 提供了哪些 lambdas 无法实现的功能?

在额外的功能方面并不多(但是,见下文)——而且,可读性在旁观者的眼中.
大多数熟悉函数式编程语言的人(尤其是 Lisp/Scheme 系列中的人)似乎都喜欢 lambda——我说大多数",绝对不是全部,因为 Guido 和我肯定是那些熟悉"(等)但认为 lambda 是 Python 中令人眼花缭乱的异常...
他后悔曾经将它接受到 Python 中,同时计划将它从 Python 3 中删除,因为它是Python 的小故障"之一.
我完全支持他.(我喜欢lambda 在Scheme...虽然它的局限性在Python,以及它不适合的奇怪方式 用剩下的语言,让我的皮肤爬行).

然而,对于成群的 lambda 爱好者来说并非如此——他们上演了 Python 历史上最接近叛乱的事情之一,直到 Guido 回溯并决定离开 lambda in.
functools 的几个可能的添加(使函数返回常量、身份等)没有发生(以避免显式复制更多 lambda 的功能),尽管 partial 当然仍然存在(它不是全部重复,也不是碍眼的).

请记住,lambda 的主体仅限于表达式,因此它有局限性.例如...:

<预><代码>>>>导入功能工具>>>f = functools.partial(int, base=2)>>>参数()>>>函数<输入'int'>>>>f.关键词{'基础':2}>>>

functools.partial 返回的函数用对自省有用的属性装饰——它包装的函数,以及它在其中修复的位置和命名参数.此外,命名参数可以立即被覆盖(修复"在某种意义上更像是默认值的设置):

<预><代码>>>>f('23', base=10)23

所以,如您所见,它绝对不像 lambda s: int(s, base=2)!-)

那样简单

是的,你可以扭曲你的 lambda 来给你一些这样的东西——例如,对于关键字覆盖,

<预><代码>>>>f = lambda s, **k: int(s, **dict({'base': 2}, **k))

但我非常希望即使是最狂热的lambda爱好者也不认为这个恐怖比部分更具可读性 调用!-).属性设置"部分更难,因为 Python 的 lambda 的主体是单个表达式"的限制(加上赋值永远不能成为 Python 表达式的一部分)......你结束通过将列表理解扩展到超出其设计限制的在表达式中伪造赋值"...:

<预><代码>>>>f = [f for f in (lambda f: int(s, base=2),)如果 setattr(f, 'keywords', {'base': 2}) 是 None][0]

现在将命名参数的可覆盖性以及三个属性的设置组合到一个表达式中,并告诉我那个的可读性如何......!

Partial application is cool. What functionality does functools.partial offer that you can't get through lambdas?

>>> sum = lambda x, y : x + y
>>> sum(1, 2)
3
>>> incr = lambda y : sum(1, y)
>>> incr(2)
3
>>> def sum2(x, y):
    return x + y

>>> incr2 = functools.partial(sum2, 1)
>>> incr2(4)
5

Is functools somehow more efficient, or readable?

解决方案

What functionality does functools.partial offer that you can't get through lambdas?

Not much in terms of extra functionality (but, see later) – and, readability is in the eye of the beholder.
Most people who are familiar with functional programming languages (those in the Lisp/Scheme families in particular) appear to like lambda just fine – I say "most", definitely not all, because Guido and I assuredly are among those "familiar with" (etc) yet think of lambda as an eyesore anomaly in Python...
He was repentant of ever having accepted it into Python whereas planned to remove it from Python 3, as one of "Python's glitches".
I fully supported him in that. (I love lambda in Scheme... while its limitations in Python, and the weird way it just doesn't fit in with the rest of the language, make my skin crawl).

Not so, however, for the hordes of lambda lovers -- who staged one of the closest things to a rebellion ever seen in Python's history, until Guido backtracked and decided to leave lambda in.
Several possible additions to functools (to make functions returning constants, identity, etc) didn't happen (to avoid explicitly duplicating more of lambda's functionality), though partial did of course remain (it's no total duplication, nor is it an eyesore).

Remember that lambda's body is limited to be an expression, so it's got limitations. For example...:

>>> import functools
>>> f = functools.partial(int, base=2)
>>> f.args
()
>>> f.func
<type 'int'>
>>> f.keywords
{'base': 2}
>>> 

functools.partial's returned function is decorated with attributes useful for introspection -- the function it's wrapping, and what positional and named arguments it fixes therein. Further, the named arguments can be overridden right back (the "fixing" is rather, in a sense, the setting of defaults):

>>> f('23', base=10)
23

So, as you see, it's definely not as simplistic as lambda s: int(s, base=2)!-)

Yes, you could contort your lambda to give you some of this – e.g., for the keyword-overriding,

>>> f = lambda s, **k: int(s, **dict({'base': 2}, **k))

but I dearly hope that even the most ardent lambda-lover doesn't consider this horror more readable than the partial call!-). The "attribute setting" part is even harder, because of the "body's a single expression" limitation of Python's lambda (plus the fact that assignment can never be part of a Python expression)... you end up "faking assignments within an expression" by stretching list comprehension well beyond its design limits...:

>>> f = [f for f in (lambda f: int(s, base=2),)
           if setattr(f, 'keywords', {'base': 2}) is None][0]

Now combine the named-arguments overridability, plus the setting of three attributes, into a single expression, and tell me just how readable that is going to be...!

这篇关于Python:为什么需要 functools.partial?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆