我有下面的代碼,我正在裝飾一個遞歸函數,但我無法理解代碼的某些部分。理解遞歸裝飾函數的困難
def deco_func(f):
def wrapper(*args):
print('Decorating', args)
res = f(*args)
print(res)
return wrapper
@deco_func
def fact(n):
if n == 0:
return 1
else:
return n * fact(n - 1)
fact(4)
注:
1. F中的包裝函數裏面實際上指向的事實功能的原始版本,因爲它來自於封閉的範圍,它的值是通過包裝關閉。
2.事實函數內部的遞歸調用調用包裝器的事實的裝飾版本。
所以根據我的理解,堆棧跟蹤將如下所示。
res = f(4)
= 4 * wrapper(3) = 4 * f(3)
= 4 * 3 * wrapper(2) = 4 * 3 * f(2)
= 4 * 3 * 2 * wrapper(1) = 4 * 3 * 2 * f(1)
= 4 * 3 * 2 * 1 * wrapper(0) = 4 * 3 * 2 * 1 * f(0)
在這點n爲0,因此F(0)將返回1,這樣棧看上去可能會像下面
res = 4 * 3 * 2 * 1 * 1
所以res
應該是24,但它的值是1我無法理解。此外,在這一點上,我得到一個異常
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
但只要我在像return res
包裝函數的底部添加一個return語句,一切工作正常。
我不明白爲什麼沒有返回正在創建一個問題在這裏,因爲在包裝函數控制內永遠不會超越res = f(*args)
直到遞歸完成。因此,像f(0)
這樣的最終調用將導致res = 5*4*3*2*1
,並且如上所示,res應該評估爲24,然後控件應該轉到下一個語句。那麼,爲什麼不使用包裝返回語句創建問題時,回報將只執行一次res
已計算
我知道我在這裏失去了一些重要的東西,但我無法從概念上弄清楚什麼出了問題,如果我們刪除返回語句。
任何人都可以回覆!!!! – Rohit