匿名函数递归(Python)
首先我们先看一下阶乘函数的递归实现函数,函数主体在定义时并不会运行函数主体而是将函数信息保存至 Frame(也就是栈)中。当函数执行时,函数主体内部用到的 fact(即自己)函数会从 Frame 中查找对应的函数并调用。这样就完成了一个递归函数的实现,从这里我们也能看到,函数是能获取到自身的。
def fact(n: int) -> int:
if n == 0:
return 1
return fact(n - 1) * n
匿名函数递归(CS61A Homeowork3 Q6 Anonymous Factorial),此处指 python 中的 lambda 函数。
而匿名函数因为无法将函数本身信息保存至 Frame 中,因此在执行时无法获取到自身也就无法完成调用(递归)。这个时候就需要我们构造一个特殊的匿名函数完成自调用的过程,也就是对应以下这段特殊代码。以下这段代码实现了最简单的递归阶乘函数。
>>> fact = (lambda f: f(f))(lambda s: lambda x: 1 if x == 1 else s(s)(x - 1) * x)
>>> fact(5)
120
我们这里需要将这个匿名函数拆分为三个部分解读:
(lambda f: f(f))(EXPRESSION):自调用函数,当传入一个函数时,会调用该函数并将该函数作为参数传入其本身。注意,这个函数只会执行一次,也就是只负责将 EXPRESSION 作为函数参数传入函数本身,为lambda s实现递归做铺垫。lambda s: lambda x: EXPRESSION:双层函数,首次调用时会将其主体发送给外层函数,即发送给 1 中的函数,并获取函数lambda s自身。此时变量 s 将保存整个lambda s函数本身,此时 s 的结构应当为Callable[[Callable], Callable[int], int]。1 if x == 1 else s(s)(x - 1) * x):阶乘函数主体,重点在于s(s)(x - 1)。由于参数 s 的结构为lambda s本身,因此需要先将 s 作为变量传入自身后传入lambda x的参数才能实现递归(即自调用),否则递归将会终止。剩下的内容实际上与前面的阶乘函数相同不在复述。
通过组合以上三个核心代码,我们就能实现匿名函数递归的功能了。实际上以上代码的核心目的就只有一个,获取函数本身以实现自调用(递归)。
以下是匿名函数的等价表达式:
from typing import Callable
def self_applicator(func: Callable[[Callable], Callable]) -> Callable:
return func(func)
def inner_function(s: Callable[[Callable], Callable]) -> Callable[[int], int]:
def factorial(n: int) -> int:
return 1 if n == 1 else n * s(s)(n - 1)
return factorial
factorial_calculator = self_applicator(inner_function)
result = factorial_calculator(5)
print(result)

本文经「原本」原创认证,作者乾坤盘,访问yuanben.io查询【SRPXYI91】获取授权信息。
本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。
转载请标明出处https://www.cnblogs.com/somata/p/18858728和作者乾坤盘。
商务合作请邮件联系somata@foxmail.com。
转载请标明出处https://www.cnblogs.com/somata/p/18858728和作者乾坤盘。
商务合作请邮件联系somata@foxmail.com。

浙公网安备 33010602011771号