在自己的体内更改函数的属性?

Mar*_*nen 7 python function decorator python-3.x

我正在尝试创建一个函数来记录它被调用的次数,我希望信息保留在函数本身内部.我试着像这样创建一个包装器:

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)
Run Code Online (Sandbox Code Playgroud)

我认为它有用,但我有一个AttributeError说法'function' object has no attribute 'count'.

我已经想到了问题:这是因为装饰器将我设置test_f为等于wrapped_f(在keep_count装饰器内部定义),并且我增加了原始的计数,f因为它test_f引用了新函数,所以不再使用它.

有没有办法在没有太多黑客攻击的情况下做到这一点?

Bre*_*arn 9

只需设置属性wrapped_f而不是f.这需要你count在定义函数后设置初始值,但这没什么大不了的:

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
Run Code Online (Sandbox Code Playgroud)

然后用你的装饰功能:

>>> test_f()
() {}
>>> test_f.count
1
>>> test_f()
() {}
>>> test_f.count
2
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为wrapped_f里面是一个局部变量keep_count.由于body wrapped_f包含一个引用wrapped_f,它有一个允许wrapped_f访问自己的闭包.

  • @MarkusMeskanen:您可以或多或少,但您必须小心,因为名称查找发生在不同的时间. (2认同)