在Python中,函数参数是按值传递的,而不是按引用传递的。如果你把一个数字传递给一个函数,函数会接收到该数字的一份副本。如果该函数修改了其参数,那么这个改变在函数外部是不可见的。
def foo(y):
y += 1
print("y=", y)
x = 10
foo(x)
print("x=", x)
在你的情况下,最直接的解决方法是将 ctr 变成全局变量。这很丑陋,因为如果你想再次调用 collatz 函数,你需要将全局变量重置为 0,但我展示这个替代方案只是为了说明你的逻辑是正确的,除了传递引用的部分。(请注意,collatz 函数现在不返回任何内容,答案在全局变量中)。
ctr = 0
def collatz(num):
global ctr
if(num != 1):
ctr+=1
if(num%2==0):
collatz(num/2)
else:
collatz(num*3+1)
ctr = 0
collatz(9)
print(ctr)
由于Python没有尾递归优化,如果Collatz序列超过1000步(这是Python默认的堆栈限制),则当前的递归代码将导致堆栈溢出。您可以通过使用循环而不是递归来避免此问题。这还可以让我们摆脱那个麻烦的全局变量。在我看来,最终结果更符合Python语言的习惯用法:
def collats(num):
ctr = 0
while num != 1:
ctr += 1
if num % 2 == 0:
num = num/2
else:
num = 3*num + 1
return ctr
print(collatz(9))
如果您想坚持使用递归函数,通常最好避免使用可变赋值,就像您试图做的那样。而不是将函数作为修改状态的“子程序”,将它们转换成更接近数学函数的东西,这些函数接收一个值并返回仅取决于输入的结果。如果您这样做,递归可能会更容易理解。我将把这留作练习,但递归函数的典型“框架”是具有检查基本情况和递归情况的if语句:
def collatz(n):
if n == 1:
return 0
else if n % 2 == 0:
return
else:
return