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

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

问题描述

部分应用很酷。 functools.partial
 >>>提供您无法通过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

functools 以某种方式更高效或可读?

解决方案



functools .partial offer,you can not
get through lambdas?


额外功能(但是,请参阅后面的内容) - 并且可读性在旁观者眼中。

大多数熟悉函数式编程语言(特别是Lisp / Scheme系列中的语言)的人都会出现喜欢 lambda 就好 - 我说最,绝对不是所有,因为Guido和我确实在那些熟悉之中等等),但想到 lambda 作为Python中的眼睛异常...

他已经悔过自己已经接受了Python,而计划去除它从Python 3开始,作为Python的小故障之一。

我完全支持他。 (我喜欢Scheme中的 ...,而Python中的限制 ,以及奇怪的方式只是不适合与其他语言,让我的皮肤抓取)。



然而,对于 lambda 爱好者 - 谁发起了一个与Python历史上曾经见过的叛乱最接近的事情,直到Guido回溯并决定离开 lambda in。

functools (使函数返回常量,标识等)的几个可能的添加没有发生(为了避免明确地重复更多 lambda 的功能),尽管 partial 当然保留了(它不是总共重复,也不是一个眼睛)。



请记住, lambda 的身体局限于一个表达式,所以它有限制。例如...:

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

functools.partial 的返回函数是装饰有用于反思的属性 - 它包装的功能,以及它在其中修复的位置和命名参数。此外,命名的参数可以被重写(固定在某种意义上说是默认设置):

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

如你所见,它的 definely 不像 lambda s:int(s,base = 2)! - >



是的,你可以扭曲你的lambda来给你一些 - 比如关键字覆盖,

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

但我非常希望即使是最热心的 lambda -lover也不会考虑 this 恐怖比部分调用更可读! - )。由于Python的 lambda 的body's a single expression限制(以及赋值不能成为Python表达式的一部分),属性设置部分更加困难)......你最终会通过扩展列表理解来完成在表达式中伪造赋值,这远远超出了它的设计限制......:

 >>>如果setattr(f,'keywords',{'base':2})是None] [0] $ b,则f = [f for f in(lambda f:int(s,base = 2),)
$ b

现在将命名参数重叠和三个属性的设置组合成一个表达式,并告诉我 会是怎样的......! - )


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天全站免登陆