我想编写一个与给定函数完全相似的函数,除了它打印执行它所消耗的时间。 就像这样:
>>> fib = profile(fib)
>>> fib(20)
time taken: 0.1 sec
10946
这是我的代码,它会在每个函数调用中打印消息。
import time
def profile(f):
def g(x):
start_time = time.clock()
value = f(x)
end_time = time.clock()
print('time taken: {time}'.format(time=end_time-start_time))
return value
return g
@profile
def fib(n):
if n is 0 or n is 1:
return 1
else:
return fib(n-1) + fib(n-2)
上面的代码将为每个fib(n-1)打印一条消息'花时间:...'。因此,会有很多消息需要花费时间:......'。我是否可以找到一种方法来打印fib(20)的执行时间而不是每次执行fib(n-1)的时间?
答案 0 :(得分:4)
我假设您的问题是"我如何编写profile
以便它只打印一条消息,即使我装饰了一个可以调用自身的函数?"
您可以跟踪当前正在计时的功能。这样,如果一个函数调用自己,你知道你已经在堆栈中进一步计时,并且不需要为第二个实例做任何事情。
def profile(f, currently_evaluating=set()):
#`currently_evaluating` will persist across all decorated functions, due to "mutable default argument" behavior.
#see also http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument
def g(x):
#don't bother timing it if we're already doing so
if f in currently_evaluating:
return f(x)
else:
start_time = time.clock()
currently_evaluating.add(f)
try:
value = f(x)
finally:
currently_evaluating.remove(f)
end_time = time.clock()
print('time taken: {time}'.format(time=end_time-start_time))
return value
return g
如果您使用的是3.X,则可以使用nonlocal
关键字减少可变的默认参数怪异。
def profile(f):
is_evaluating = False
def g(x):
nonlocal is_evaluating
if is_evaluating:
return f(x)
else:
start_time = time.clock()
is_evaluating = True
try:
value = f(x)
finally:
is_evaluating = False
end_time = time.clock()
print('time taken: {time}'.format(time=end_time-start_time))
return value
return g
答案 1 :(得分:1)
您可以使用课程作为分析器:
import time
class ProfileRecursiveFib(object):
def __call__(self, func):
self.start_time = time.clock()
def g(x):
return func(x)
self.end_time = time.clock()
print('time taken: {0}'.format(self.end_time - self.start_time))
return g
profile = ProfileRecursiveFib()
@profile
def fib(n):
if n is 0 or n is 1:
return 1
else:
return fib(n-1) + fib(n-2)
result = fib(20)
print(result)
这打印时间(仅一次)和结果:
time taken: 9.056212818586247e-07
10946
答案 2 :(得分:0)
我理解你所期待的答案。你的代码中有很小的错误,只需按照下面的代码进行操作,
import time
def profile(f):
start_time=time.time()
def g(x):
value = f(x)
return value
print("time taken : %f seconds"%(time.time()-start_time))
return g
def fib(n):
if n is 0 or n is 1:
return 1
else:
return fib(n-1) + fib(n-2)
x = profile(fib)
print(x(20))