嗨,我是函数式编程的新手。我做的是
>>> g=lambda x:x*2
>>> f=g
>>> g=lambda x:f(f(x))
>>> g(9)
36
现在,它没有创建g
作为非终止递归函数 - g(x)
被转换为一个新函数,它给出了结果g(g(x))
。
>>> f=g
>>> g=lambda x:f(f(x))
>>> f(8)
RuntimeError: maximum recursion depth exceeded
根据g(x)的第一个定义,我希望将g
转换为一个给出结果g(g(g(x)))
的函数。为什么不呢?是否有可能以这种方式创建一个新函数,导致g(g(g(...(g(x))....)))
进行一定数量的迭代?
答案 0 :(得分:6)
当您第二次f = g
时,f变为lambda x: f(x)
。闭包是按名称创建的,而不是按值创建的。
使用辅助函数变得容易:
def compose(f, g):
return lambda x: f(g(x))
square = lambda x:x*2
g = square
for i in xrange(4):
g = compose(g, square)
答案 1 :(得分:4)
在python中,变量是映射到值的名称,而不是值本身(一切都是引用)。此外,您可以将lambda视为存储可以评估的文本。以下将说明
a = 2
f = lambda x: a*x
f(2) # This gives 4
a = 3
f(2) # This gives 6
这应该清楚你为什么得到无限递归。
在回答你关于递归的问题时,这里有一点可能做的黑客
g = lambda x, n: n > 0 and g(x, n-1)**2 or x
然后g(2,3)
将为(((2)^2)^2)^2 = 256
。
答案 2 :(得分:2)
这个
g=lambda x:x*2
f=g
g=lambda x:f(x)
相当于:
f=lambda x:x*2
g=lambda x:f(x)
当你致电g
时,你会得到在全局(或封闭)范围内定义的f
。
你期待的是:
f=lambda x:x*2
g=lambda x, f=f:f(x)
在评估lambda
表达式时捕获外部作用域中f的值。