python - list variable not storing proper result in recursion

删除回忆录丶 提交于 2021-02-11 16:10:09

问题


I am trying to store all possible parenthesisation of a list through recursion.

Example: printRange(0,3) Answer will be [[0],[1], [2]], [[0], [1, 2]], [[0, 1], [2]], [[0, 1, 2]]

I could get a right answer when i tried to print it in side the function.When i try to store the result and print it after i am not getting the desired result.

The code is as follows:

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

When i run the above code i got:

[[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]]]

why res variable is not storing the intended result?


回答1:


This is happening because cans is a list of lists, and those inner lists get mutated. You need to append a deep copy of cans to res, i.e. a copy that makes copies of the internal lists. You can do that with deepcopy from the copy module, or just write a simple deepcopy that works for a list of lists.

Here's a repaired version of your code.

#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

output

[[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]]]

Note that it's generally not a good idea to use a list or other mutable object as a default argument because default arguments are assigned when the function is defined, not when it's called, and that can cause surprising behaviour. It doesn't actually cause problems for your code, but it's still a good idea to avoid default mutable args unless you need that "interesting" behaviour, eg so it can be used as a memoization cache, and even then you should use a comment explaining that you're doing it on purpose. :) See “Least Astonishment” and the Mutable Default Argument for further details.


I would approach this task in a slightly different way, with one of my favourite "toys": a recursive generator.
def brackets(n):
    if n == 0:
        yield [[0]]
    else:
        for seq in brackets(n - 1):
            yield seq + [[n]]
            yield seq[:-1] + [seq[-1] + [n]]

for seq in brackets(3):
    print seq

output

[[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]]

If you do actually want a list containing all the results, just pass the generator to the list constructor:

res = list(brackets(2))
print res

output

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


来源:https://stackoverflow.com/questions/42885694/python-list-variable-not-storing-proper-result-in-recursion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!