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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With