[英]Python decorator to time recursive functions properly
我正在编写一段代码以用于学习目的,并且我想比较使用不同算法对列表进行排序所需的时间。 我尝试使用装饰器,但由于 mergeSort function 是递归的,它给了我每次递归的结果。 如果可能的话,我想找到一种方法来总结结果。 由于我对装饰师很陌生,我不确定在这种情况下可以做什么。 有没有办法使用装饰器来实现这个目标?
import random
import functools
import time
def timeIt(func):
@functools.wraps(func)
def newfunc(*args, **kwargs):
startTime = time.time()
func(*args, **kwargs)
elapsedTime = time.time() - startTime
print('function [{}] finished in {} ms'.format(
func.__name__, int(elapsedTime * 1000)))
return newfunc
@timeIt
def mergeSort(L):
if len(L) > 1:
mid = len(L) // 2
left = L[:mid]
right = L[mid:]
mergeSort(left)
mergeSort(right)
i = j = k = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
L[k] = left[i]
i += 1
else:
L[k] = right[j]
j += 1
k += 1
while i < len(left):
L[k] = left[i]
i += 1
k += 1
while j < len(right):
L[k] = right[j]
j += 1
k += 1
@timeIt
def selectionSort(L):
for fillslot in range(len(L) - 1, 0, -1):
maxpos = 0
for location in range(1, fillslot + 1):
if L[location] > L[maxpos]:
maxpos = location
temp = L[fillslot]
L[fillslot] = L[maxpos]
L[maxpos] = temp
randomList = random.sample(range(10000), 10000)
mergeSort(randomList.copy())
selectionSort(randomList.copy())
Output:
[...] truncated
function [mergeSort] finished in 7 ms
function [mergeSort] finished in 15 ms
function [mergeSort] finished in 33 ms
function [mergeSort] finished in 68 ms
function [selectionSort] finished in 2049 ms
你可以用另一个 function 把它包起来……
import random
import functools
import time
def timeIt(func):
@functools.wraps(func)
def newfunc(*args, **kwargs):
startTime = time.time()
func(*args, **kwargs)
elapsedTime = time.time() - startTime
print('function [{}] finished in {} ms'.format(
func.__name__, int(elapsedTime * 1000)))
return newfunc
def mergeSort(L):
if len(L) > 1:
mid = len(L) // 2
left = L[:mid]
right = L[mid:]
mergeSort(left)
mergeSort(right)
i = j = k = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
L[k] = left[i]
i += 1
else:
L[k] = right[j]
j += 1
k += 1
while i < len(left):
L[k] = left[i]
i += 1
k += 1
while j < len(right):
L[k] = right[j]
j += 1
k += 1
def selectionSort(L):
for fillslot in range(len(L) - 1, 0, -1):
maxpos = 0
for location in range(1, fillslot + 1):
if L[location] > L[maxpos]:
maxpos = location
temp = L[fillslot]
L[fillslot] = L[maxpos]
L[maxpos] = temp
@timeIt
def timedSelectionSort(L):
selectionSort(L)
@timeIt
def timedMergeSort(L):
mergeSort(L)
randomList = random.sample(range(10000), 10000)
timedSelectionSort(randomList.copy())
timedMergeSort(randomList.copy())
您可以在包装器 function 上设置一个属性(在示例中为_entered
)作为标志,以便如果设置了该属性,它可以判断它在递归调用中:
def timeIt(func):
@functools.wraps(func)
def newfunc(*args, **kwargs):
if not hasattr(newfunc, '_entered'): # enter only if _entered is not set
newfunc._entered = True # set _entered
startTime = time.time()
func(*args, **kwargs)
elapsedTime = time.time() - startTime
print('function [{}] finished in {} ms'.format(
func.__name__, int(elapsedTime * 1000)))
del newfunc._entered # remove _entered
return newfunc
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.