假设我有一个二叉搜索树[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
如果我运行以下函数,我想知道递归函数执行了多少次(在下面的例子中,它是31)
def loopBST(root):
if not root:
return
loopBST(root.left)
loopBST(root.right)
我可以通过创建一个全局变量来获得这个
global ind
ind = 0
def loopBST(root):
global ind
ind += 1
if not root:
return
loopBST(root.left)
loopBST(root.right)
loopBST(bsttree)
变量ind
将为31。
问题是,如何在ind
函数中创建dfs
而不是创建全局变量?
答案 0 :(得分:4)
您可以使用参数。
def loopBST(root, times=0):
times += 1
if not root:
return times
times = loopBST(root.left, times=times)
times = loopBST(root.right, times=times)
return times
loopBST(bsttree)
答案 1 :(得分:4)
您可以返回执行次数:
def loopBST(root):
if not root:
return 1
return 1 + loopBST(root.left) + loopBST(root.right)
答案 2 :(得分:2)
如果你不想重写你的递归函数,你也可以在一个使用某种计数器计算它的函数中修饰它。实施示例:
更新:我已经更改了答案,但旧答案保留在答案的最后 //更新
这里假设你在some_module.py中有一些递归函数:
# From some_module.py
def factorial(x):
return factorial(x-1)*x if x > 1 else 1
def cumsum(x):
return cumsum(x-1) + x if x > 1 else 1
def loopBST(root):
# ... your code
并且您想要应用装饰器来计算运行的递归次数。这里,代码在some_function()
内执行,表明您不必将计数变量保留在全局范围内。 (参见注释)(此外,递归函数仍在全局空间中)
# Main file:
from functools import wraps, partial
from collections import defaultdict
# import the two recursion functions from some_module.py
from some_module import cumsum, factorial, loopBST
def some_function():
global factorial, cumsum, loopBST
def counting_recursion(fn, counter):
@wraps(fn)
def wrapper(*args, **kwargs):
counter[fn.__name__] += 1
return fn(*args, **kwargs)
return wrapper
counters = defaultdict(int)
my_deco = partial(counting_recursion, counter=counters)
factorial = my_deco(factorial)
cumsum = my_deco(cumsum)
loopBST = my_deco(loopBST)
print(factorial(3))
# 6
print(cumsum(5))
# 15
factorial_count = counters[factorial.__name__]
cumsum_count = counters[cumsum.__name__]
loopBST_count = counters[loopBST.__name__] # Equals 0: were not called in my example
print('The "{}" function ran {} times'.format(factorial.__name__, factorial_count))
print('The "{}" function ran {} times'.format(cumsum.__name__, cumsum_count))
# The "factorial" function ran 3 times
# The "cumsum" function ran 5 times
一些修改/变化:
可以直接修饰递归函数,而不是使用my_deco = partial(counting_recursion, counter=counters)
:
cumsum = counting_recursion(cumsum, counter=counters)
factorial = counting_recursion(factorial, counter=counters)
loopBST = counting_recursion(loopBST, counter=counters)
而不是使用fn.__name__
来识别被调用的函数,counting_recursion
- 函数可以重写为:
def counting_recursion(fn, counter):
@wraps(fn)
def wrapper(*args, **kwargs):
counter[wrapper] += 1
return fn(*args, **kwargs)
return wrapper
然后,从counters
字典中读取数字:
factorial_count = counters[factorial]
cumsum_count = counters[cumsum]
loopBST_count = counters[loopBST]
如果您想了解有关包装功能的更多信息,请查看https://stackoverflow.com/a/25827070/1144382以及wraps上的文档
旧例子:
from functools import wraps, partial
class Counter:
def __init__(self, start_count=0):
self._counter = start_count
def __repr__(self):
return str(self._counter)
def count(self):
self._counter += 1
counter = Counter()
def counting_recursion(fn, counter):
@wraps(fn)
def wrapper(*args, **kwargs):
counter.count()
return fn(*args, **kwargs)
return wrapper
my_deco = partial(counting_recursion, counter=counter)
@my_deco
def factorial(x):
return factorial(x-1)*x if x > 1 else 1
print(factorial(3))
# 6
print('The {} function ran {} times'.format(factorial.__name__, counter))
# The factorial function ran 3 times
要在你的情况下实现这一点,只需制作一些计数器并装饰你的功能:
@my_deco
def loopBST(root):
# ...
print(counter._counter)
# prints number of counts
当然,你不必让Counter
- 类来打电话给counter.count()
,你也可以有一个计数器字典,例如counts[loopBST] += 1
或仅包含单个元素count_list[0] += 1
的数组。 (请参阅本答案顶部的代码示例)(整个要点是“隐藏”重新分配变量时未重写的引用中的值,这就是整数计数的原因{ {1}}无效。)
答案 3 :(得分:0)
也许你可以尝试使用类的实例,这样它可能比使用关键字参数更干净。更不用说您可以在实例中存储其他数据。
这是一个Python 2.7类。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="images"/>