假设我想将x**2
从0集成到1。我使用scipy.integrate.quad
来做到这一点:
from scipy import integrate
def f(x): return x**2
I = integrate.quad(f, 0, 1)[0]
print(I)
问题:是否有办法知道f
调用用户定义的函数quad
的次数?我想这样做,是因为我很想知道quad
已经使用了多少个来评估积分。
答案 0 :(得分:7)
好的。使用呼叫计数包装器:
import functools
def counted_calls(f):
@functools.wraps(f)
def count_wrapper(*args, **kwargs):
count_wrapper.count += 1
return f(*args, **kwargs)
count_wrapper.count = 0
return count_wrapper
并将包装的版本传递到quad
:
wrapped = counted_calls(f)
integrate.quad(wrapped, 0, 1)
print(wrapped.count)
Demo,呼叫计数为21。
我特别避免使用全局计数器或在counted_calls
定义上使用f
作为装饰器(尽管您可以根据需要将其用作装饰器),以使其易于使用分开计数。使用全局变量或将其用作装饰器,您必须记住每次都要手动重置计数器。
答案 1 :(得分:3)
每当调用f
时,只需添加到全局变量即可:
from scipy import integrate
count = 0
def f(x):
global count
count += 1
return x ** 2
I = integrate.quad(f, 0, 1)[0]
print(I)
print('called', count, 'times')
答案 2 :(得分:3)
您可以执行以下操作:
from scipy import integrate
class FWrap(object):
def __init__(self):
self.count = 0
def f(self, x):
self.count += 1
return x ** 2
fwrap = FWrap()
f = lambda x: fwrap.f(x)
I = integrate.quad(f, 0, 1)[0]
print(I)
print(fwrap.count)
我可能更喜欢全局变量,尽管可能有更简单的方法。 (编辑:There is)
答案 3 :(得分:1)
在您的小示例中,您可以使用变量或其他一些自定义代码来跟踪,但是,如果您不想继续编辑代码(也许在大型程序中,您希望跟踪许多函数的调用) ,最好使用trace和/或某些调用图形库。还有更标准的方法,如果需要,还可以提供诸如计时数据之类的其他功能。
我以前曾与Gprof一起使用过此工具,对此感到满意,它不仅适用于Python:https://github.com/jrfonseca/gprof2dot
答案 4 :(得分:0)
您可以在函数内部添加一个简单的计数器,以计算运行特定代码的次数。
答案 5 :(得分:0)
我认为在之前(并且非常有效)的答案中没有探讨过的一个有趣系统是为您的函数定义计数器属性(例如 count
)。
根据我的个人经验,我一直避免使用全局变量,这可能是一种简单但同时更安全的方法。
from scipy import integrate
def f(x):
return x**2
f.count += 1
f.count = 0
I = integrate.quad(f, 0, 1)[0]
print(I)
print(f.count)