python-list变量在递归中未存储正确的结果

python-list变量在递归中未存储正确的结果,python,list,recursion,Python,List,Recursion,我试图通过递归存储列表中所有可能的括号 示例:printRange(0,3) 答案将是[[0]、[1]、[2]]、[[0]、[1,2]]、[[0,1]、[2]]、[[0,1,2]] 当我尝试在函数中打印结果时,我可以得到正确的答案。当我尝试存储结果并在没有得到所需结果后打印结果时 代码如下: res=[] def printRange(st,size,cans=[]): if(st==size): res.append([]+cans) print c

我试图通过递归存储列表中所有可能的括号

示例:
printRange(0,3)
答案将是
[[0]、[1]、[2]]、[[0]、[1,2]]、[[0,1]、[2]]、[[0,1,2]]

当我尝试在函数中打印结果时,我可以得到正确的答案。当我尝试存储结果并在没有得到所需结果后打印结果时

代码如下:

res=[]
def printRange(st,size,cans=[]):


    if(st==size):
        res.append([]+cans)
        print cans

    l=[]

    for i in range(st,size):
        l.append(i)
        tmp=[]+cans
        tmp.append(l)
        printRange(i+1,size,[]+tmp)

printRange(0,3)
print res
当我运行上述代码时,我得到:

[[0], [1], [2]]

[[0], [1, 2]]

[[0, 1], [2]]

[[0, 1, 2]]

[[[0, 1, 2], [1, 2], [2]], [[0, 1, 2], [1, 2]], [[0, 1, 2], [2]], [[0, 1, 2]]]

为什么res变量没有存储预期结果?

发生这种情况是因为
cans
是一个列表列表,而这些内部列表会发生变化。您需要在
res
中附加一份
cans
的深度副本,即制作内部列表副本的副本。您可以使用
copy
模块中的
deepcopy
来实现这一点,也可以编写一个简单的deepcopy,用于列表列表

这是您的代码的修复版本

#from copy import deepcopy

def deepcopy(list2d):
    return [u[:] for u in list2d]

res = []
def printRange(st, size, cans=[]):
    if(st == size):
        res.append(deepcopy(cans))
        print cans

    l = []
    for i in range(st, size):
        l.append(i)
        tmp = [] + cans
        tmp.append(l)
        printRange(i+1, size, tmp)

printRange(0, 4)
print res
输出

[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [[0], [1, 2], [3]], [[0], [1, 2, 3]], [[0, 1], [2], [3]], [[0, 1], [2, 3]], [[0, 1, 2], [3]], [[0, 1, 2, 3]]]
[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2]], [[0], [1, 2]], [[0, 1], [2]], [[0, 1, 2]]]

请注意,使用列表或其他可变对象作为默认参数通常不是一个好主意,因为默认参数是在定义函数时指定的,而不是在调用函数时指定的,这可能会导致意外行为。它实际上不会给您的代码带来问题,但最好避免使用默认的可变参数,除非您需要这种“有趣”的行为,例如,它可以用作备忘录缓存,即使这样,您也应该使用注释来解释您是有意这样做的。:)有关更多详细信息,请参阅


我会以一种稍微不同的方式来完成这项任务,使用我最喜欢的“玩具”之一:递归

输出

[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [[0], [1, 2], [3]], [[0], [1, 2, 3]], [[0, 1], [2], [3]], [[0, 1], [2, 3]], [[0, 1, 2], [3]], [[0, 1, 2, 3]]]
[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2]], [[0], [1, 2]], [[0, 1], [2]], [[0, 1, 2]]]
如果您确实想要一个包含所有结果的列表,只需将生成器传递给
列表
构造函数:

res = list(brackets(2))
print res
输出

[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [[0], [1, 2], [3]], [[0], [1, 2, 3]], [[0, 1], [2], [3]], [[0, 1], [2, 3]], [[0, 1, 2], [3]], [[0, 1, 2, 3]]]
[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2]], [[0], [1, 2]], [[0, 1], [2]], [[0, 1, 2]]]

之所以会发生这种情况,是因为
cans
是一个列表列表,而这些内部列表会发生变化。您需要在
res
中附加一份
cans
的深度副本,即制作内部列表副本的副本。您可以使用
copy
模块中的
deepcopy
来实现这一点,也可以编写一个简单的deepcopy,用于列表列表

这是您的代码的修复版本

#from copy import deepcopy

def deepcopy(list2d):
    return [u[:] for u in list2d]

res = []
def printRange(st, size, cans=[]):
    if(st == size):
        res.append(deepcopy(cans))
        print cans

    l = []
    for i in range(st, size):
        l.append(i)
        tmp = [] + cans
        tmp.append(l)
        printRange(i+1, size, tmp)

printRange(0, 4)
print res
输出

[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [[0], [1, 2], [3]], [[0], [1, 2, 3]], [[0, 1], [2], [3]], [[0, 1], [2, 3]], [[0, 1, 2], [3]], [[0, 1, 2, 3]]]
[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2]], [[0], [1, 2]], [[0, 1], [2]], [[0, 1, 2]]]

请注意,使用列表或其他可变对象作为默认参数通常不是一个好主意,因为默认参数是在定义函数时指定的,而不是在调用函数时指定的,这可能会导致意外行为。它实际上不会给您的代码带来问题,但最好避免使用默认的可变参数,除非您需要这种“有趣”的行为,例如,它可以用作备忘录缓存,即使这样,您也应该使用注释来解释您是有意这样做的。:)有关更多详细信息,请参阅


我会以一种稍微不同的方式来完成这项任务,使用我最喜欢的“玩具”之一:递归

输出

[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [[0], [1, 2], [3]], [[0], [1, 2, 3]], [[0, 1], [2], [3]], [[0, 1], [2, 3]], [[0, 1, 2], [3]], [[0, 1, 2, 3]]]
[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2]], [[0], [1, 2]], [[0, 1], [2]], [[0, 1, 2]]]
如果您确实想要一个包含所有结果的列表,只需将生成器传递给
列表
构造函数:

res = list(brackets(2))
print res
输出

[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [[0], [1, 2], [3]], [[0], [1, 2, 3]], [[0, 1], [2], [3]], [[0, 1], [2, 3]], [[0, 1, 2], [3]], [[0, 1, 2, 3]]]
[[0], [1], [2], [3]]
[[0], [1], [2, 3]]
[[0], [1, 2], [3]]
[[0], [1, 2, 3]]
[[0, 1], [2], [3]]
[[0, 1], [2, 3]]
[[0, 1, 2], [3]]
[[0, 1, 2, 3]]
[[[0], [1], [2]], [[0], [1, 2]], [[0, 1], [2]], [[0, 1, 2]]]

顺便说一句,代码中使用的技术称为。您可能还对此相关问题感兴趣。顺便说一句,代码中使用的技术称为。您也可能对此相关问题感兴趣