Python:递归函数中的变量绑定
我在使用一个类似下面的函数时,遇到了一些奇怪的情况:
def foo(x):
if int(x)!=4:
x = raw_input("Wrong guess, please enter new value: " )
foo(x)
else:
print "Good Job! %s was right"%x
return x
value = foo(x=raw_input("Guess a Number between 1 and 10: "))
print value
比如说,如果我输入“1”,然后“2”,接着“3”,最后“4”,我得到的输出是:
Good Job! 4 was right
2
这让我感到困惑,因为这个函数似乎能正确识别出答案,但在识别之后,它却返回了第二个输入的值,而不是最新的那个。
有没有人能解释一下这个递归函数中“x”的绑定到底是怎么回事?
3 个回答
2
试试下面的代码:
def foo(x):
if int(x)!=4:
x = raw_input("Wrong guess, please enter new value: " )
return foo(x)
else:
print "Good Job! %s was right"%x
return x
value = foo(x=raw_input("Guess a Number between 1 and 10: "))
print value
你可以把每次调用函数 foo 看作是创建了一个新的变量 x。因此,递归调用会生成一系列的变量,比如 x1、x2、x3,等等。所以当一个函数调用结束后,你的局部变量 x 并没有改变。这就是为什么你得到的结果是 2,而不是最后一次递归调用的赋值结果(4)。如果你想在函数中改变传入的变量,你需要通过引用(或者对象)来传递它,而不是通过值来传递。想了解更多细节,可以看看这篇文章。
3
主要问题是你在
def foo(x):
if int(x)!=4:
x = raw_input("Wrong guess, please enter new value: " )
foo(x) # <-- need return
else:
print "Good Job! %s was right"%x
return x
value = foo(x=raw_input("Guess a Number between 1 and 10: "))
print value
这里缺少一个 return
。
发生的事情是,它调用了 foo(1)
,这个值不等于4,然后把 x
赋值为2,而这就是 x
最后得到的值,所以
- 你的递归函数
foo(x)
返回了一个值,但这个值没有被赋给任何东西,也没有从递归调用中返回。 - 最后
x
得到的值是2,所以最开始的foo(1)
返回的就是这个值。
所以你可以选择
x = foo(x)
或者
return foo(x)
在我标记的那一行
4
让我们来看看吧!
value = foo(raw_input())
# foo is the same as in the question, I won't repeat it here
print value
在你的 foo 函数里面,你会得到这个:
# foo(1) calls foo(2) and sets x to 2
# foo(2) calls foo(3) and sets x to 3
# foo(3) calls foo(4) and sets x to 4
# foo(4) does:
print "Good Job! 4 was right"
return 4 # to foo(3)
# foo(3) does:
return 4 # to foo(2)
# foo(2) does:
return 3 # to foo(1)
# foo(1) does:
return 2 # to main
因为从最外层的递归返回给 main 的值是 2
,所以 value
就保持这个值。
要解决这个问题,你可以选择把它改成循环的方式:
def iter_foo(x):
while int(x) != 4:
x = raw_input("Wrong guess. Try again! ")
print "Good Job! %s was right" % x
return x
或者让每一次递归都返回新函数的结果
def recurse_foo(x):
if int(x) != 4:
return foo(raw_input("Wrong guess. Try again! "))
else:
print "Good Job! %s was right!" % x
return x