在递归函数中更改列表对象的值

时间:2017-06-04 13:16:29

标签: python python-2.7

def divide(alist):
    # when the list have only one element, it should return the 0
    if len(alist) == 1:
        alist[:] = list([0])

    else:
        middle = len(alist) / 2
        divide(alist[:middle])
        divide(alist[middle:])
temp = [1, 2, 3, 4, 5, 6]
divide(temp)
print temp

在我的函数中,在递归之后,我想得到[0, 0, 0, 0, 0, 0],但temp仍然是[1, 2, 3, 4, 5, 6]。我还使用alist[:] = list([0])来确保重新分配alist。

为什么呢?参考文献有问题吗?

2 个答案:

答案 0 :(得分:2)

您的代码不起作用slicing因为divide(alist[:middle])创建了一个新列表,所以alist在第一次递归之后没有引用temp不再。

return结果更常见,而不是试图在调用参数中创建副作用,例如:

def divide(alist):
    # when the list have only one element, it should return the 0
    if len(alist) == 1:
        return [0]
    middle = len(alist) // 2
    return divide(alist[:middle]) + divide(alist[middle:])

print(divide(temp))
# [0, 0, 0, 0, 0, 0]

显然,这是相对无稽之谈,但我假设您只是设置结构来执行特定的操作。

如果你真的想用副作用做这个(不推荐!!!)那么你需要保留leftright索引并使用它来最终分配{{1} },例如:

[0]

如果你想保留原始的调用签名,那么你可以使用def divide(alist, left, right): middle = (right - left) // 2 # when the list have only one element, it should return the 0 if middle == 0: alist[left:right] = [0] else: divide(alist, left, left+middle) divide(alist, left+middle, right) temp = [1, 2, 3, 4, 5, 6] divide(temp, 0, len(temp)) print(temp) # [0, 0, 0, 0, 0, 0] 函数来处理递归,这将允许你默认args,但实际上只有_inner()没有它们:

return _inner(0, len(alist))

答案 1 :(得分:1)

下次提问时请提及您的目标。我的猜测是你不需要递归和就地修改你的列表。

所以我的第一个答案是提出就地修改而不递归:

def set_to_zero(alist):
    alist[:] = [0 for _ in alist]

temp = [1, 2, 3, 4, 5, 6]
set_to_zero(temp)
print(temp)
# [0, 0, 0, 0, 0, 0]

事实证明,你需要递归而没有就地修改,因为你想写一个merge sort

  

合并排序最常见的实现没有排序; [5]   因此,必须为输入分配输入的内存大小   要存储的已排序输出(请参阅下面的仅需要的版本   n / 2个额外空格)。

这里是一个clean implementation of the sort,带有一些调试行。这是一个关于SO(Mergesort python)的相关问题,有许多实现。