Python:递归列表处理会改变原始列表。

9

我想要做的是递归处理一个列表。我对Python还不太熟悉,当所有代码都编写并执行时,我遇到了一个奇怪的问题:在调用递归函数后,列表返回了改变。为了测试这个问题,我写了以下代码:

def recur(n):
    n.append(len(n))
    print '>',n
    if n[-1]<5: recur(n)
    print '<',n

并调用该函数:

recur([])

这是结果:
> [0]
> [0, 1]
> [0, 1, 2]
> [0, 1, 2, 3]
> [0, 1, 2, 3, 4]
> [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4, 5]

我期望看到的是

> [0]
> [0, 1]
> [0, 1, 2]
> [0, 1, 2, 3]
> [0, 1, 2, 3, 4]
> [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4, 5]
< [0, 1, 2, 3, 4]
< [0, 1, 2, 3]
< [0, 1, 2]
< [0, 1]
< [0]

对于简单的整数变量来说,情况是一样的:

def recur(n):
    n=n+1
    print '>',n
    if n<5: recur(n)
    print '<',n

recur(0)
> 1
> 2
> 3
> 4
> 5
< 5
< 4
< 3
< 2
< 1

我应该如何解决这种情况,我对此有什么误解吗?

你的问题“python:递归列表处理”不是一个问题。 - Phil Frost
@PhilFrost,但是“我该如何解决这种情况,我理解错了什么?”是一个问题。 - StoryTeller - Unslander Monica
@StoryTeller:我无法确定你是否在讽刺。我并不是说这是一个坏问题;我是说顶部的大标题没有用问句的形式表达。这很重要,因为当有人对他们的列表如何被改变感到困惑时,他们不会搜索“递归列表处理”。他们可能会搜索类似于“为什么每次调用函数时我的列表都会改变?”的内容。 - Phil Frost
@PhilFrost,您的批评不够清晰,而且似乎有些不公正。我认为标题不一定要用问句形式,但我同意它应该更紧密地与问题相关。希望我的编辑能有所改进。 - StoryTeller - Unslander Monica
2个回答

9

你的函数所有递归调用操作的是同一个列表。你需要创建一个副本:

def recur(n):
    n.append(len(n))
    print '>',n
    if n[-1]<5: recur(n[:])  # <<<< Note the [:]
    print '<',n

有一些好的解释可以在如何通过引用传递变量?的答案中找到。


3

正如其他答案所指出的,您正在就地修改列表。 您可以复制列表和/或使用不可变数据结构(例如元组):

def recur(n=()):
    if len(n) > 4:
         return n
    return recur(n + (len(n),))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接