我正在寻找的是一个调用其参数的函数,以便我可以将它用作装饰器来轻松处理闭包。写起来很容易(如果我关心我甚至可以使用*args
和**kwargs
):
def unclosure(f):
return f()
@unclosure
def count():
x = 0
def _count():
nonlocal x
x += 1
return x
return _count
assert count() == 1
assert count() == 2
但我觉得这是一个非常简单的想法,这个已经内置到某个地方的python标准库。我已经检查了functools
,但我不知道还有哪些地方可以查看,而且我似乎无法找到输入谷歌的正确信息。有谁知道这是否存在?
答案 0 :(得分:4)
这通常是使用类而不是闭包来实现的。
class Count:
def __init__(self):
self.x = 0
def __call__(self):
self.x += 1
return self.x
count = Count()
assert count() == 1
assert count() == 2
答案 1 :(得分:3)
你要求的是与 1 apply
函数相同,它在Python中从1.0到2.7存在,但从2.3开始被弃用。 2 < / SUP>
事实上,你可以在2.7:
中使用它@apply
def count():
x=[0]
def _count():
x[0] += 1
return x[0]
return _count
assert count() == 1
assert count() == 2
为何弃用?
Python并不经常需要它。当它与Python没有的其他东西(如合成运算符)结合使用时,它在函数式语言中非常有用,用于编写一种不能以非常Python的方式读取的代码,并且执行速度非常慢。 / p>
但在2.3之前,这并不完全正确。琐碎的案例,您可以自己编写:lambda f: f()
或def apply(f): return f()
。但是对于非平凡的例子,在解压缩语法之前,你无法完成转发&#34;对于参数,所以你无法模拟apply
的每次使用。这就是它被添加的原因。并且,一旦不再需要它,它就被弃用了。
有些人抱怨说自己编写它比使用C内置版略慢 - 但没有人想出一个有用的用例,但额外的函数调用间接并没有做到整个事情在第一时间使用太慢。如果你仔细研究从Python 2.3-2.6编写的大量开源代码,几乎没有一个使用apply
。并且没有人编写和发布C扩展来保留或apply
以便他们可以继续使用它。在过去十年中,没有人为3.x写过。
当&#34; Python 3000&#34; (什么变成了3.0)正在讨论中,这是消除所有已弃用功能的第一件事。其中包括不被弃用的内容,但Guido没有看到需要,例如reduce
。你可以阅读邮件列表档案,看看人们出来捍卫一些功能和结构,通常是成功的 - 但我不记得,并且无法找到,任何人都试图捍卫apply
。唯一的讨论是PEP 3100中的摘要:
apply()
:使用f(*args, **kw)
代替[2]
...链接指向(断开的链接)Guido&#39; s Python Regrets presentation,其中没有更多的参数而不是将其称为&#34;遗物&#34;。
<子> 1。或者更确切地说,apply
的较弱版本没有任何参数。
<子> 2。 IIRC(我无法找到相关的文档),这发生在Python有一个真正的概念之后#34;弃用&#34;。它被标记为非必要的&#34;并移至文档页面的末尾,只有大约2.5或2.6的某个地方,自2.3以来它被追溯弃用。
答案 2 :(得分:-1)
据我所知,标准库中不存在这样的功能。
我怀疑这样做的原因是这种功能几乎没有任何用例。甚至你的装饰器实际上也不是一个好的用例,因为它不是一个正确实现的装饰器。如您所见,它不维护函数的名称或docstring:
@unclosure
def count():
"""docstring"""
x = 0
def _count():
nonlocal x
x += 1
return x
return _count
print(count) # <function count.<locals>._count at 0x7f3282dac620>
print(count.__doc__) # None
这意味着实际上它应该像这样实现:
import functools
def unclosure(f):
func = f()
functools.update_wrapper(func, f)
return func
@unclosure
def count():
"""docstring"""
x = 0
def _count():
nonlocal x
x += 1
return x
return _count
print(count) # <function count at 0x7f3892f7c620>
print(count.__doc__) # docstring