在一个装饰的装饰之外创建访问函数属性 [英] Accessing function attribute created in a decorator outside that decorator
问题描述
我要计算时代给定函数被调用的次数。
I want to count the number of times a given function has been called.
所以,我做了一个 countcalls
装饰给我的功能,这得到每次通话递增 __ callcount
属性。够简单了。
So, I made a countcalls
decorator to give my functions a __callcount
attribute which gets incremented on each call. Simple enough.
我的问题是获得 __ callcount
值回出来以后。
My issue is getting the __callcount
value back out later.
下面是我的code:
import functools
def countcalls(f):
f.__callcount = 0
@functools.wraps(f)
def _countcalls(*args, **kwds):
f.__callcount += 1
print(' Called {0} time(s).'.format(f.__callcount))
return f(*args, **kwds)
return _countcalls
@countcalls
def fib(n):
if n < 0:
raise ValueError('n must be > 0')
if n == 0 or n == 1:
return 1
return fib(n-1) + fib(n-2)
if __name__ == '__main__':
print('Calling fib(3)...')
x = fib(3)
print('fib(3) = {0}'.format(x))
print('Calling fib(3) again...')
x = fib(3)
print('fib(3) = {0}'.format(x))
print('fib was called a total of {0} time(s).'.format(fib.__callcount))
产生以下输出(Python的3.3.0):
Which generates the following output (Python v3.3.0):
Calling fib(3)...
Called 1 time(s).
Called 2 time(s).
Called 3 time(s).
Called 4 time(s).
Called 5 time(s).
fib(3) = 3
Calling fib(3) again...
Called 6 time(s).
Called 7 time(s).
Called 8 time(s).
Called 9 time(s).
Called 10 time(s).
fib(3) = 3
fib was called a total of 0 time(s).
为什么 FIB .__ callcount
在最后一行等于 0
?由于输出显示, __ callcount
被递增, FIB
。
Why does fib.__callcount
equal 0
on the last line? As the output shows, __callcount
gets incremented, and persists between calls of fib
.
我是什么失踪?
推荐答案
那么,这里的原因,一点帮助后。谢谢你们!
Well, here's the reason, after a bit of help. Thanks guys!
问题是功能是不可变的。例如。
The issue is that functions are immutable. e.g.
>>> def f(func):
... return func()
...
>>> def g():
... return 'sunflower seeds'
...
>>> id(g)
139636515497336
>>> g = f(g)
>>> id(g)
139636515515112
因此,要获得功能˚F
我们的定义分配 __ callcount
属性的唯一办法 countcalls
是返回从 callcount
。但是,我们已经返回内部函数 _countcalls
。我们可以同时返回˚F
和 _countcalls
但搅乱 @countcalls
修饰语法。
So, the only way to get the function f
we assigned the __callcount
attribute to in the definition of countcalls
is to return that function from callcount
. But we're already returning the inner function _countcalls
. We can return both f
and _countcalls
but that messes up the @countcalls
decorator syntax.
您仍然可以这样来做,它只是并不像pretty。
You can still do it this way, it's just not as pretty.
import functools
def countcalls(f):
f.__callcount = 0
@functools.wraps(f)
def _countcalls(*args, **kwds):
f.__callcount += 1
print(' Called {0} time(s).'.format(f.__callcount))
return f(*args, **kwds)
return f, _countcalls
def fib(n):
if n < 0:
raise ValueError('n must be > 0')
if n == 0 or n == 1:
return 1
return fib(n-1) + fib(n-2)
if __name__ == '__main__':
counter, fib = countcalls(fib)
print('Calling fib(3)...')
x = fib(3)
print('fib(3) = {0}'.format(x))
print('Calling fib(3) again...')
x = fib(3)
print('fib(3) = {0}'.format(x))
print('fib was called a total of {0} time(s).'.format(counter.__callcount))
长话短说,只需使用类从Python的装饰图书馆。 :D
这篇关于在一个装饰的装饰之外创建访问函数属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!