【问题标题】:Python recursion updates an arrayPython递归更新数组
【发布时间】:2021-12-21 18:42:45
【问题描述】:

我可以问一个关于 Python 递归的问题吗?我想检查一下这背后的逻辑,为什么它能够不断更新结果?

问题: 构造 DFS 递归以附加满足指定条件的所有子节点,例如,如果节点的结束指示符为 True,我们将将此节点添加到数组中。此递归将在另一个函数中使用。

  1. 我的代码:
    def dfs(self, level, ls):
        # if we meet the end of a level, this level’s information will be added to the returned list
        if level.end:
            ls.append(level.info)
        # go further to explore this level’s children, even an end is met. 
        for c in level.child:
            ls = self.dfs(level.child[c], ls)
        return ls

DFS 将被调用:

ls = self.dfs(self.curr, [])

层级是自定义的Trie:

class Trie:
    def __init__(self):
        self.child = collections.defaultdict(Trie)
        # self.child = {}
        self.end = False 
        self.w = ''
        self.f = 0

我不确定为什么这个 ls 会在每次 for 循环迭代中得到更新,然后传递到下一次迭代。我也很惊讶,以下代码也可以工作:

        for c in level.child:
            self.dfs(level.child[c], ls)

不返回ls。我不确定为什么会这样?

提前感谢您的帮助。

最好的,

朴素的 Python 学习者

【问题讨论】:

  • level.child[c] 是字典吗?请包括该定义的类。我不确定我是否完全理解了您的问题,但请注意 ls 正在就地修改,因此 ls = self.dfs(level.child[c], ls) 只是将 ls 重新分配给自己。
  • 是的,你是对的。我将把课程包括在这里。谢谢。
  • @joseville 这里的问题是ls = self.dfs 会自行更新。但是为什么self.dfs 不赋值也会更新ls?谢谢。

标签: python recursion depth-first-search


【解决方案1】:

当列表传递到dfs 时,传递的不是list 中的当前值,而是内存中list 的引用(指针)。只有一个list。这称为按引用传递。

同样,当代码将dfs 的输出分配给ls 时,这实际上是将指向list 对象的指针替换为指向list 对象的指针,即它什么也不做。

Python FAQ 中甚至还有与此相关的答案。在this answer 中有一些进一步的阅读示例。

如果您想让您的代码按照您的想法运行,您可以构建一个新的list,而不是编辑单个list。这样做有一些原因,但是对于普通的list,它相当昂贵并且价值不大。要查看它的实际效果,请将 append 调用更改为:

    ls = ls + [level.info]

【讨论】:

  • 非常感谢您的回答。我想这就是我要找的。我们可以说list 这里的行为更可能是一个全局变量,并且会在每次迭代中得到更新吗? list += [level.info] 将创建一个新的内存空间,并用list + [level.info] 分配值。但是,list.append() 只会更新值,不会更新引用。
  • 请记住,在 Python 中参数是通过赋值传递的。 (这是否意味着函数只从参数中取出值?)由于赋值只是创建对对象的引用,所以调用者和被调用者中的参数名称之间没有别名,(调用者和被调用者中的参数完全不相关,比如你说返回的ls 是一个新对象。)因此本身没有引用调用。
  • 第二个 StackOverflow 答案救了我。原始的 Python 文档不是那么清楚。惊人的。感谢您的帮助。
  • Ned Bachelder 在这里很好地解释了按分配调用:youtube.com/watch?v=_AEJHKGk9ns。另外,记得点赞并接受对您有帮助的答案。
  • 感谢您的帮助。
猜你喜欢
  • 2019-05-18
  • 1970-01-01
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
相关资源
最近更新 更多