在其自己的内部更改函数的属性? [英] Change an attribute of a function inside its own body?

查看:132
本文介绍了在其自己的内部更改函数的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个函数来保持它被调用的次数,并且我希望信息留在函数本身中。
我尝试创建一个如下所示的包装:

  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)

我认为它可以工作,但我得到了一个 AttributeError ,它说'function'object has no attribute'count'



我已经想出了问题:这是因为装饰器将我的 test_f 等于 wrapped_f (定义在 keep_count 装饰器中),并且我正在增加原来的 f ,因为 test_f 引用了新函数,所以不再使用它。



有没有办法做到这一点,而没有太多的黑客行为?

只要设置在赞美 wrapped_f 而不是 f 。这需要您在定义函数后设置初始 count ,但这没什么大不了的:

  def keep_count(f):
@ functools.wrap(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_f keep_count 中的局部变量。因为 wrapped_f 包含对 wrapped_f 的引用,所以它得到一个闭包,它允许 wrapped_f 来访问自己。


I'm attempting to create a function that keeps count of the times it has been called, and I want the information to stay inside the function itself. I tried creating a wrapper like so:

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)

I thought it'd work, but I got an AttributeError saying 'function' object has no attribute 'count'.

I already figured the problem: It's because the decorator sets my test_f to equal to the wrapped_f (defined inside the keep_count decorator), and I'm increasing the count of the original f, which is no longer used since test_f refers to the new function.

Is there a way to do this without too much of hacking?

解决方案

Just set the attribute on wrapped_f instead of f. This requires you to set the initial count after defining the function, but that's no big deal:

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

Then with your decorated function:

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

This works because wrapped_f is a local variable inside keep_count. Since the body of wrapped_f contains a reference to wrapped_f, it gets a closure allowing wrapped_f to access itself.

这篇关于在其自己的内部更改函数的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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