如果我正确理解你想要什么,理论上是不可能的;您似乎正在描述的转换是一种会对等效函数产生不同影响的转换,具体取决于可能不会以编译形式保留的源代码的表面细节。例如,考虑给定函数的以下两个版本:
def a (n, acc):
print('called a(%d,%d)' % (n, acc))
if n == 0: return acc
return a (n - 1, acc + n)
def a (n, acc):
print('called a(%d,%d)' % (n, acc))
if n == 0: return acc
ret = a (n - 1, acc + n)
return ret
显然它们在功能上是相同的。在源代码中,唯一的区别是前者直接在某个表达式上使用return,而后者将该表达式的结果保存到局部变量中,然后在该变量上使用return。编译后的形式,完全没有区别。
现在考虑“修补”版本:
def a (n, acc):
print('called a(%d,%d)' % (n, acc))
if n == 0: return acc
return lambda: a (n - 1, acc + n)
def a (n, acc):
print('called a(%d,%d)' % (n, acc))
if n == 0: return acc
ret = a (n - 1, acc + n)
return lambda: ret
显然这些是非常不同的:例如,如果n 是3 而acc 是0,那么前者打印called a(3,0) 并返回一个打印called a(2,3) 的函数并返回一个打印@ 的函数987654330@ 并返回一个打印called a(0,6) 并返回6 的函数,而后者打印called a(3,0) 和called a(2,3) 和called a(1,5) 和called a(0,6) 并返回一个函数,该函数返回一个函数,该函数返回一个返回的函数6.
更广泛的区别在于,第一个“修补”函数在每次调用新返回值时执行一个计算步骤,而第二个“修补”版本在初始调用期间执行所有计算步骤,并且简单为了娱乐,安排了一系列后续的通话。只要有副作用(例如打印消息,或者例如递归太深以至于溢出堆栈),这种差异就会很重要。 调用者是否引入副作用也很重要:请注意,这些函数只会递归,直到其他一些代码重新定义a,此时版本之间存在差异计划继续重新调用a 和已经完成所有调用的版本。
由于您无法区分两个“未修补”版本,因此您显然无法生成转换所暗示的不同“已修补”版本。