<p>我真的不喜欢这种方法,但这里有一个你正在做的修正版本:</p>
<pre><code>from collections import defaultdict
import threading
functions_on_stack = threading.local()
def record_function_on_stack(f):
def wrapped(*args, **kwargs):
if not getattr(functions_on_stack, "stacks", None):
functions_on_stack.stacks = defaultdict(int)
functions_on_stack.stacks[wrapped] += 1
try:
result = f(*args, **kwargs)
finally:
functions_on_stack.stacks[wrapped] -= 1
if functions_on_stack.stacks[wrapped] == 0:
del functions_on_stack.stacks[wrapped]
return result
wrapped.orig_func = f
return wrapped
def function_is_on_stack(f):
return f in functions_on_stack.stacks
def nested():
if function_is_on_stack(test):
print "nested"
@record_function_on_stack
def test():
nested()
test()
</code></pre>
<p>它处理递归、线程和异常。在</p>
<p>我不喜欢这种方法有两个原因:</p>
<ul>
<li>如果函数被进一步修饰,它就不起作用了:它必须是最终的装饰器。在</li>
<li>如果要使用它进行调试,则意味着您必须在两个位置编辑代码才能使用它;一个用于添加装饰器,另一个用于使用它。只检查堆栈会更方便,因此您只需编辑正在调试的代码中的代码。在</li>
</ul>
<p>更好的方法是直接检查堆栈(可能作为本机的速度扩展),如果可能,找到一种方法在堆栈帧的生存期内缓存结果。(不过,如果不修改Python内核,我不确定这是否可行。)</p>