使用装饰器计算递归函数运行时间的一个问题
问题来源:python最新版中的递归课后作业中,要求分别计算普通递归、尾递归和迭代方式相应的解决时间。本人尝试使用之前使用的装饰器知识去解决,代码如下:import time
def timee(func): #装饰器函数,用于计算函数运行时间
def inner(n):
t1 = time.time()
func(n)
t2 = time.time()
print(f"耗时:{t2-t1}")
return inner
@timee
def fibRecur(n): #待计算运行时间的斐波拉契函数(普通递归算法实现)
if n == 1 or n == 2:
return 1
else:
return fibRecur(n-1) + fibRecur(n-2)
fibRecur(12) #12为计算斐波拉契数列第12项的结果
运行结果:
耗时:0.0
耗时:0.0
Traceback (most recent call last):
File "F:\Programs\Python\HomeWork\fibtime.py", line 16, in <module>
fibRecur(12)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
File "F:\Programs\Python\HomeWork\fibtime.py", line 5, in inner
func(n)
File "F:\Programs\Python\HomeWork\fibtime.py", line 15, in fibRecur
return fibRecur(n-1) + fibRecur(n-2)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
想请问出现上述异常的原因是什么?如何改进代码? 你的代码中出现这个错误是因为你在装饰器函数中没有返回 func(n) 的结果。你的装饰器函数只是计算了运行时间,然后打印了这个时间,但并没有返回原函数的计算结果。在斐波那契数列的计算过程中,你需要将每一步的结果返回给上一步以便计算,所以在这里你需要返回 func(n) 的结果。
你可以将你的装饰器函数修改如下:
import time
def timee(func): #装饰器函数,用于计算函数运行时间
def inner(n):
t1 = time.time()
result = func(n) # 收集函数结果
t2 = time.time()
print(f"耗时:{t2-t1}")
return result # 返回函数结果
return inner
@timee
def fibRecur(n): #待计算运行时间的斐波拉契函数(普通递归算法实现)
if n == 1 or n == 2:
return 1
else:
return fibRecur(n-1) + fibRecur(n-2)
这样修改后,你的装饰器函数除了计算运行时间之外,还会返回原函数的计算结果,这样在斐波那契数列的计算过程中就不会出现 'NoneType' 错误了。
但这样一来,你的装饰器会对每一次递归都进行计时,而我们通常需要的是整个函数从开始到结束的运行时间,而不是每一次递归的运行时间。所以在实际使用中,可能需要进一步优化你的装饰器以实现对整个函数运行时间的计算。 本帖最后由 sfqxx 于 2023-6-26 19:39 编辑
出现上述异常的原因是在装饰器函数 inner 中,你没有正确传递返回值。这导致了斐波那契递归函数的递归调用返回了 None,无法进行加法操作。
要改进代码,你需要在递归函数 fibRecur() 中使用 return 语句返回计算结果,以确保每个递归调用都返回相应的值。同时,在装饰器函数 inner 中,你需要将递归函数的返回值返回给调用者。
以下是改进后的代码示例:
import time
def timee(func):
def inner(n):
t1 = time.time()
result = func(n)
t2 = time.time()
print(f"耗时:{t2-t1}")
return result
return inner
@timee
def fibRecur(n):
if n == 1 or n == 2:
return 1
else:
return fibRecur(n-1) + fibRecur(n-2)
fibRecur(12)
改进后的代码会正确计算斐波那契递归函数的运行时间,并给出正确的结果。
(无限递归)
页:
[1]