Python内置装饰器调用它的参数?

时间:2018-05-25 17:52:17

标签: python closures decorator standard-library

我正在寻找的是一个调用其参数的函数,以便我可以将它用作装饰器来轻松处理闭包。写起来很容易(如果我关心我甚至可以使用*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,但我不知道还有哪些地方可以查看,而且我似乎无法找到输入谷歌的正确信息。有谁知道这是否存在?

3 个答案:

答案 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