我有一个简单的装饰器来跟踪函数调用的运行时间:
def timed(f):
def caller(*args):
start = time.time()
res = f(*args)
end = time.time()
return res, end - start
return caller
Run Code Online (Sandbox Code Playgroud)
这可以如下使用,并返回函数结果和执行时间的元组.
@timed
def test(n):
for _ in range(n):
pass
return 0
print(test(900)) # prints (0, 2.69e-05)
Run Code Online (Sandbox Code Playgroud)
很简单.但现在我想将它应用于递归函数.将上述包装器应用于递归函数会导致嵌套元组具有每个递归调用的时间,如预期的那样.
@timed
def rec(n):
if n:
return rec(n - 1)
else:
return 0
print(rec(3)) # Prints ((((0, 1.90e-06), 8.10e-06), 1.28e-05), 1.90e-05)
Run Code Online (Sandbox Code Playgroud)
编写装饰器以便正确处理递归的优雅方法是什么?显然,如果定时函数可以包装调用:
@timed
def wrapper():
return rec(3)
Run Code Online (Sandbox Code Playgroud)
这将给出结果和时间的元组,但我希望所有这些都由装饰器处理,这样调用者就不必担心为每个调用定义一个新函数.想法?
我看到了一些我不希望的isinstance方法的奇怪行为.有人可以帮我确定为什么会这样吗?
我有一个模块sandbox.py,我在创建模块时用它来修改模块.我还有一个二叉树类binary_tree.py和一个BST类bst.py,它继承自二叉树实现并添加了树的排序约束.我也有一些在树上运行的实用方法,比如BFS,DFS等.
问题是:Bst类(BST节点)是Node的子类(通用二叉树节点).我的实用程序方法有一些检查以确保它们的参数是Node或其子类型的实例:
def bfs(n: Node, process=None):
. . .
assert isinstance(n, Node)
# print for debugging
print("util.py:", isinstance(n, Node))
. . .
Run Code Online (Sandbox Code Playgroud)
在bfs方法中,断言通过以下调用,然后打印打印:
tree = Bst("A")
bfs(tree, lambda n: print(n.data, end=' ')) # Ignore the implementation, just know this enters the method
util.py: True
Run Code Online (Sandbox Code Playgroud)
正如所料.但是,在sandbox.py中,同一个调用打印为False:
from trees.binary_tree import Node
from trees.util import *
from trees.bst import Bst
print("sandbox.py:", isinstance(Bst, Node))
sandbox.py: False
Run Code Online (Sandbox Code Playgroud)
为什么isinstance在从不同位置调用时会返回两个不同的东西,即使这两个参数属于同一个类?
如果它相关,我的目录结构是这样的:
sandbox.py
trees/
binary_tree.py
bst.py
util.py
Run Code Online (Sandbox Code Playgroud)
在bst.py中,Bst定义如下:
Bst(Node):
. . .
Run Code Online (Sandbox Code Playgroud)