Python:为什么一个函数能够在另一个函数中改变数组?我猜是';这是一个范围问题

Python:为什么一个函数能够在另一个函数中改变数组?我猜是';这是一个范围问题,python,python-3.x,scope,Python,Python 3.x,Scope,我很困惑。我不明白如何通过在DFS中进行更改,在numIslands中更新访问的 我的理解是,访问过的,一旦传递到DFS,就像是原始的访问过的的副本 不是这样吗 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

我很困惑。我不明白如何通过在
DFS
中进行更改,在
numIslands
中更新访问的

我的理解是,
访问过的
,一旦传递到
DFS
,就像是原始的
访问过的
的副本

不是这样吗

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
类解决方案:
def DFS(自我、网格、访问、i、j):
如果i<0或j<0或i>=len(网格)或j>=len(网格[0]),或访问了[i][j]或网格[i][j]='0':
返回
访问[i][j]=正确
self.DFS(网格、访问、i+1、j)
自助式DFS(网格、访问、i-1、j)
self.DFS(网格、访问、i、j+1)
自助式DFS(网格、访问、i、j-1)
def numIslands(self,grid:List[List[str]])->int:
如果不是网格:返回0
visited=[[False for i in range(len(grid[0]))]for j in range(len(grid))]
计数=0
对于范围内的i(len(网格)):
对于范围内的j(len(网格[0]):
如果网格[i][j]='1'并且访问了[i][j]==False:
self.DFS(网格、访问、i、j)#待办事项
计数+=1
返回计数
我的理解是,访问,一旦进入DFS,就像一个原始访问的副本

事实并非如此。Python从不为您创建隐式副本。如果将对象传递给函数,则不会生成该对象的副本。您只需在函数范围内为与
visted
关联的对象赋予另一个名称
visted

要使
DFS
numIslands
中独立于
访问的
运行,您需要制作一份深度拷贝:

from copy import deepcopy

. . .

self.DFS(grid, deepcopy(visited), i, j)
尽管这通常不是一个好主意,因为
deepcopy
是一个相当昂贵的函数,我认为您无论如何都不想在这里这么做。该算法要求
DFS
mutate
visitored
。如果它没有返回值,
DFS
将不会执行任何操作

我的理解是,访问,一旦进入DFS,就像一个原始访问的副本

事实并非如此。Python从不为您创建隐式副本。如果将对象传递给函数,则不会生成该对象的副本。您只需在函数范围内为与
visted
关联的对象赋予另一个名称
visted

要使
DFS
numIslands
中独立于
访问的
运行,您需要制作一份深度拷贝:

from copy import deepcopy

. . .

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

尽管这通常不是一个好主意,因为
deepcopy
是一个相当昂贵的函数,我认为您无论如何都不想在这里这么做。该算法要求
DFS
mutate
visitored
。如果它没有返回值,
DFS
将不会做任何事情,因为它从不返回值。

Python通过引用传递,而不是通过值传递。出现在
DFS()
中的
已访问的
是从
numIslands()
传递的同一对象的不同名称。您可以在不更改原始值的情况下将某些内容重新分配给名称
已访问
,但如果您更改名称
已访问
所指的对象(通过使用
已访问[i][j]=True更改其特定索引),则更改将持续,因为它是同一对象。“就像是原作的复制品。不是这样吗?“不,你不是。你可以用创建一个副本,这是否回答了你的问题?Python通过引用传递,而不是通过值传递。出现在
DFS()
中的
访问的
是从
numIslands()传递的同一对象的不同名称
。您可以在不更改原始值的情况下,将某些内容重新分配给名称
已访问
,但如果更改名称
已访问
所指的对象(通过使用
已访问[i][j]=True更改其特定索引),则更改将持续,因为它是同一对象。”就像是一本原著。不是这样吗?“不,你不是。你可以用创建一个副本,这是否回答了你的问题?我们可以添加:``list.copy()``返回列表对象的
浅拷贝
,而不是
深拷贝
。深拷贝和浅拷贝之间的区别是:“浅拷贝构造一个新的复合对象,然后(尽可能地)`向其中插入对原始中找到的对象的引用。“和”深度副本构造一个新的复合对象,然后递归地向其中插入原始中找到的对象的副本“。来源:我们可以添加:``list.copy()```返回列表对象的
浅拷贝
,而不是
深拷贝
。深拷贝和浅拷贝之间的区别是:“浅拷贝构造一个新的复合对象,然后(尽可能)在其中插入对原始对象的引用。”和“深拷贝构造一个新的复合对象,然后,递归地将在原始文件中找到的对象的副本插入其中。源: