【问题标题】:Python: Why is one function able to mutate an array in another function? I guess it's an issue of scopePython:为什么一个函数能够改变另一个函数中的数组?我想这是范围的问题
【发布时间】:2020-10-30 15:01:37
【问题描述】:

我很困惑。我不明白如何通过更改DFS 来更新numIslands 中的visited

我的理解是visited,一旦传入DFS,就像是原始visited的副本。

不是这样吗?

class Solution:
    def DFS(self, grid, visited, i, j):
        if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or visited[i][j] or grid[i][j] == '0':
            return
        visited[i][j] = True
        self.DFS(grid, visited, i+1, j)
        self.DFS(grid, visited, i-1, j)
        self.DFS(grid, visited, i, j+1)
        self.DFS(grid, visited, i, j-1)
        
    def numIslands(self, grid: List[List[str]]) -> int:
        if not grid: return 0
        visited = [[False for i in range(len(grid[0]))] for j in range(len(grid))]
        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1' and visited[i][j] == False:
                    self.DFS(grid, visited, i, j) # TODO
                    count += 1
        return count

【问题讨论】:

  • Python 通过引用而不是值传递。出现在DFS() 中的visited 是您从numIslands() 传递的同一对象的不同名称。您可以在不更改原始值的情况下重新分配名称visited,但如果您更改名称visited所指的对象(通过更改特定索引visited[i][j] = True),那么更改将持续存在,因为它是同一个对象。
  • "就像是访问的原件的副本。不是这样吗?"不,你不是。您可以使用docs.python.org/3.8/library/copy.html 创建一个副本

标签: python python-3.x scope


【解决方案1】:

我的理解是,visited 一旦传入 DFS,就像是原始访问过的副本。

这不是真的。 Python 从不为您制作隐式副本。如果将对象传递给函数,则不会生成它的副本。您只是在函数范围内为与visited 关联的对象提供第二个名称visited

要真正让DFSnumIslands 中独立于visited 运行,您需要进行深层复制:

from copy import deepcopy

. . .

self.DFS(grid, deepcopy(visited), i, j)

虽然这通常不是一个好主意,因为deepcopy 是一个相当昂贵的功能,而且我认为您无论如何都不想在这里这样做。该算法要求DFS 变异visited。如果没有,DFS 不会做任何事情,因为它从不返回值。

【讨论】:

  • 我们可以添加:``` list.copy()``` 返回列表对象的shallow copy,而不是deep copy。深和浅的区别:“浅拷贝构造一个新的复合对象,然后(尽可能)将引用插入到原始对象中找到的对象。”和“深拷贝构造一个新的复合对象,然后递归地将在原始对象中找到的对象的副本插入其中”。来源:docs.python.org/3/library/copy.html
猜你喜欢
  • 2022-07-07
  • 2022-10-06
  • 2017-01-04
  • 2012-10-28
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多