为什么计数器变量在同一个函数中重置为旧值?

why does the counter variable reset to old value within the same function?

我正在尝试获取嵌套列表中所有项目的计数。当代码遍历所有项目时,计数器仅设置为非嵌套列表项目。发生了什么以及如何更正此代码?

def countarr(arr,count):
    
    if len(arr) == 0:
        return count

    else:
        
        if type(arr[0]) != list:
            count += 1
            print(arr[0],count)
        else:
            print ("inner")
            countarr(arr[0],count)

    return countarr(arr[1:],count)
    
count=0
arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr(arr, count))

变量不会神奇地重置。它们只被设置为你给它的值。修改局部变量的值不会影响另一个函数中另一个变量的值,即使它具有相同的名称。举个例子:

def foo(count):
   print(count)
   count += 1 
   print(count)

def bar()
   count = 0
   print(count)
   foo(count)
   print(count)

bar()

递归也是一样。每个递归函数调用都有自己的局部变量副本,就像 foo()bar() 每个都有一个名为 count 的变量,它们彼此独立。

要修复递归函数,只需 return 来自每个可能的 if...else 分支的 count 的值。您已经在其中两个分支中执行了此操作,但您只打印了其他两个分支中的值而没有 return 它。

countint 类型的变量。将 int 作为参数传递给 python 中的函数时,仅传递值,而不传递实际变量。所以,当递归调用“修改count”时,它实际上修改了变量的副本,而不是原来的。所以,原文没有更新。

此外,当您执行递归调用时:countarr(arr[0]),您没有使用该调用的 return 值。您可以简单地在递归调用前面添加 count =,以检索递归调用的 returned 值:

def countarr0(arr,count):
    if len(arr) == 0:
        return count
    else: 
        if not isinstance(arr[0], list):
            count += 1
        else:
            count = countarr0(arr[0], count)
    return countarr0(arr[1:], count)
    
arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr0(arr, 0))
# Answer:  11

但是,将参数 count 传递给递归调用并不是很有用。递归调用不需要知道 count 的当前值。递归调用应该只计算嵌套子列表中有多少元素,我们将把它的 return 值添加到我们当前的计数中:

def countarr1(arr):
    if len(arr) == 0:
        return 0
    else:
        count = 0
        if isinstance(arr[0], list):
            count += countarr1(arr[0])
        else:
            count += 1
        count += countarr1(arr[1:])
        return count

arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr1(arr))
# Answer:  11

请注意,使用递归来导航子列表是个好主意;但是在 python 中使用递归来迭代列表是一个坏主意。在 python 中,递归比 for 循环慢得多;此外,当您编写 arr[1:] 时,会创建一个全新的数组副本!那是非常低效的。相反,我们可以使用循环来迭代列表:

def countarr2(arr):
    count = 0
    for x in arr:
        if isinstance(x, list):
            count += countarr2(x)
        else:
            count += 1
    return count

arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr2(arr))
# Answer:  11