Python 在函数自身的主体内更改函数的属性?

Python 在函数自身的主体内更改函数的属性?,python,function,python-3.x,decorator,Python,Function,Python 3.x,Decorator,我正在尝试创建一个函数,该函数记录调用它的次数,我希望信息留在函数本身中。 我尝试创建一个包装器,如下所示: def keep_count(f): f.count = 0 @functools.wraps(f) def wrapped_f(*args, **kwargs): f(*args, **kwargs) f.count += 1 return wrapped_f @keep_count def test_f(*args,

我正在尝试创建一个函数,该函数记录调用它的次数,我希望信息留在函数本身中。 我尝试创建一个包装器,如下所示:

def keep_count(f):
    f.count = 0
    @functools.wraps(f)
    def wrapped_f(*args, **kwargs):
        f(*args, **kwargs)
        f.count += 1
    return wrapped_f

@keep_count
def test_f(*args, **kwargs):
    print(args, kwargs)
我原以为它会起作用,但我得到一个
属性错误
“function”对象没有属性“count”

我已经解决了这个问题:这是因为装饰器将我的
test\u f
设置为等于
wrapped\u f
(在
keep\u count
装饰器中定义),并且我正在增加原始
f
的计数,因为
test\u f
引用了新函数,所以不再使用它


有没有一种方法可以在不进行太多黑客攻击的情况下做到这一点?

只需将属性设置为
wrapped\u f
而不是
f
。这要求您在定义函数后设置初始
计数
,但这没什么大不了的:

def keep_count(f):
    @functools.wraps(f)
    def wrapped_f(*args, **kwargs):
        f(*args, **kwargs)
        wrapped_f.count += 1
    wrapped_f.count = 0
    return wrapped_f
然后使用您的装饰功能:

>>> test_f()
() {}
>>> test_f.count
1
>>> test_f()
() {}
>>> test_f.count
2

这是因为
wrapped\u f
keep\u count
中的局部变量。由于
wrapped\u f
的主体包含对
wrapped\u f
的引用,因此它得到一个闭包,允许
wrapped\u f
访问自身。

为什么不使用类?这就是类的用途——创建有状态上下文来运行函数in@AdamSmith既然python函数是对象,它们不能同时维护状态吗?@wegry当然可以。你也可以用一把钳子把两块板钉在一起:)事实上,这段代码在Python 3.4上运行得很好。@MarkusMeskanen这里没有AttributeError。哇,我一直认为你不能在其内部使用函数。。。再说一次,从我记事起我就一直在使用递归函数,我不明白为什么我不能这样做。O只是有一种误解。好吧,谢谢你的回答,我想你每天都能从旧东西中学到新东西!:)@马库斯梅斯卡宁:你可以,或多或少,但你必须小心,因为名字查找发生在不同的时间。啊,是的,谢谢…:)我会继续深入研究,我会尽快接受。