为什么我的python变量在递归过程中全局作用?

时间:2019-04-17 18:00:10

标签: python variables recursion

我有一个递归函数,它不能按我希望的方式工作。在函数内部,我有一个名为sum的变量。我希望变量是局部变量/每个函数调用都不同,以便最终的总和成为所有较早函数调用的总和。但是,似乎变量是全局作用的,因此每次调用该函数时,sum变量都设置为0,这就是最后返回的结果。我在列表上遇到了同样的问题:对于每个函数调用,在所有不同的递归框架中都从my_list中删除了一个元素,而不仅仅是我想要的本地框架。这是变量在python递归期间应该如何工作的方式吗?如果是这样,如何更改代码以使其按我希望的方式工作?

顺便说一句,该函数的目的是找出列表中是否存在一个子集,该子集的总数为n,但这与理解我所遇到的问题无关。

我搜索了类似的帖子,并且发现有人争辩说除非您使用return语句返回如下函数,否则您不调用递归:

返回f(n-x,remove(list,x))

但是,如果是这种情况,我看不到如何既可以返回函数又可以将值同时添加到总和中。

list1 = [3, 5, 1, 2, 5, 3, 4]

# removes an element from the list, and returns the result
def remove(list_, x):
    list_.remove(x)
    return list_

# recursive function
# should return 1 or more if there exists a combination of numbers in the list
# that add up to the number n
def f(n, my_list):
    sum = 0

    if n == 0:
        return 1
    if len(my_list) == 0:
        return 0
    for x in my_list:
        sum += f(n - x, remove(my_list, x))

    return sum


print(f(15, list1))

列表中有一个子集,其总数为15:例如(5,1,5,4),因此输出应至少为1,但是由于变量全局作用,因此输出始终为0。

3 个答案:

答案 0 :(得分:0)

仅创建一个列表对象,因此,当元素被删除时,所有位置都将被删除。您需要先复制列表,然后再向下传递。试试这个:

list1 = [3, 5, 1, 2, 5, 3, 4]

# removes an element from the list, and returns the result
def remove(list_, x):
    list_.remove(x)
    return list_

# recursive function
# should return 1 or more if there exists a combination of numbers in the list
# that add up to the number n
def f(n, my_list):
    sum = 0

    if n == 0:
        return 1
    if len(my_list) == 0:
        return 0
    for x in my_list:
        sum += f(n - x, remove(list(my_list), x))

    return sum


print(f(15, list1))

答案 1 :(得分:0)

list1 = [3, 5, 1, 2, 5, 3, 4]

# removes an element from the list, and returns the result
def remove(list_, x):
    del list_[x]
    return list_

# recursive function
# should return 1 or more if there exists a combination of numbers in the list
# that add up to the number n
def f(n, my_list, total):
    if n == 0:
        return 0
    if len(my_list) == 0:
        return total
    else:
        total += my_list[0]

    return f(n - 1, remove(my_list, 0), total)



print(f(15, list1, 0))

您的代码不适用于递归算法,我将代码更新为递归。

答案 2 :(得分:0)

sumint;这是不可变的-您在例程的每个条目上都会获得一个局部变量。

但是,my_list是函数的可变参数;所有呼叫共享同一个对象。而不是传递列表,而是传递截断列表的副本。您可以通过切片更轻松地执行此操作。尝试使用类似在线解决方案的方法来解决该问题:在每个递归步骤中,在一个包含前导元素的分支中前进;在没有它的情况下前进

def f(n, my_list):
    if n == 0:
        return True
    if len(my_list) == 0:
        return False
    if f(n, my_list[1:]):
        return True
    if f(n - my_list[0], my_list[1:])
        return True

    return False