2 回答

TA貢獻1842條經驗 獲得超21個贊
您可以使用 lambda 演算之類的東西來避免賦值和自引用,將兩者都替換為對匿名函數參數的訪問。例如:
fact = (lambda f: f(f))(lambda f: (lambda n: n*f(f)(n-1) if n else 1))
在Ideone中測試。
下面提供了一些詳細信息,以獲取進一步的背景信息。
我知道lambda演算以強大(圖靈完備)但極簡主義的“編程語言”而聞名。它只使用變量的標識符,變量可以是綁定的(幾乎是函數參數)也可以是未綁定的(在談論表達式的某些部分時最相關)。所以這感覺就像一個很好的起點。
在 lambda 演算中表示遞歸的規范方法是使用不動點組合器。雖然該組合器可以在Python語法中天真地表達,但急切的評估會導致無限遞歸。
注釋中提到的 https://rosettacode.org/wiki/Y_combinator#Python 的代碼通過延遲其中一個遞歸調用直到函數實際被調用來避免這種無限遞歸。但我更愿意把對這種方法的詳細解釋留給一個單獨的答案。
在lambda演算中表達遞歸的核心思想是什么?將函數作為參數傳遞給自身。所以我從這個開始:
lambda f: f(f) # λ f.f f
我需要向該函數傳遞另一個將函數作為值的函數。喜歡。該調用的結果應該是一個函數,該函數應將 an 作為計算階乘的參數。我的第一個近似值是將自己視為遞歸調用的表達式,所以我首先有這個:lambda f: …
n
f
(lambda f: f(f))(lambda f: (lambda n: n*f(n-1) if n else 1))
但后來我意識到這是錯誤的:它本身不是遞歸調用,因為它是接受參數的函數 。遞歸調用也是如此,導致我在開始時打印的解決方案。f
f
f
f(f)

TA貢獻1111條經驗 獲得超0個贊
這很可能絕對不是問題所在,但是通過一些/魔術,您可以重建所調用的函數...inspecttypes
import types, inspect
def fact(n):
frame = inspect.currentframe()
fn = types.FunctionType(frame.f_code, frame.f_globals)
if n == 0:
return 1
return n * fn(n - 1)
print(fact(10))
添加回答
舉報