1

我将列表的副本传递给了一个函数,但由于某种原因原始列表发生了变化。我尽我所能,这完全不合逻辑,或者我做错了什么。

maze="""XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXX            XXXXXXXXXXXXXXXXXXXXX EXX
XXXXXXXXXXXXXX XXX          XXXX     XXX
XX XX           XXX XXXXXXX XXXX XXXXXXX
XX XX XXXXXXXXX XX  XXXXXXX XXXX XXXXXXX
XX XX XXXXXXX XXXXX XXXXXXX XXXX XXXXXXX
XX XX XXXX    XXXXX XXXXX             XX
XX XX XXXX XX XXXXX   XXX XXXXXXXXXXXXXX
XX XX XXXX XX XXXXXXX XXX     XXXX    XX
XX XX      XX     XXX XXXXXXX XXXX XX XX
XX XXXXXXXXXX XXX XXX XXXXXXX      XXXXX
XX      XXXXX XXX XXXXXX      XXXX XXXXX
XXXX XX XXXXX XXX XX     XXXX XXXX   XXX
XXXX XX XXXXX XXX XX XXXXXXXX XXXXXX XXX
XX   XX XXX   XXX XX XXXXX      XXXX XXX
XXXX XX     XXXXX    XXXXX XXXXXXX XXXXX
XXXX XXXXXXXXXXXXXXXXXXXXX XXXXXXX   XXX
XXXX                XXX        XXXXX XXX
XXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXX XXX
XXX              XXXXXX XXXXXX XXXXX XXX
XXX XXXXXXXXXXXXXXXXX   XX     XXXXX  XX
XXX             XX XX XXXX XXXXXXXXXX XX
XS  XXXXXXXX XXXXX    XXXX            XX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"""
grid=maze.split("\n")
for x in xrange(len(grid)):
    grid[x]=list(grid[x])
row=len(grid)
col=len(grid[0])
def check(maze,x,z,row,col):
    lim=0
    if z+1<col and maze[x][z+1]=="X":
        lim+=1
    if x+1<row and maze[x+1][z]=="X":
        lim+=1
    if z-1>=0 and maze[x][z-1]=="X":
        lim+=1
    if x-1>=0 and maze[x-1][z]=="X":
        lim+=1
    return lim
def get_pos(grida,row,col):
    for l in xrange(100):
        for x in xrange(len(grida)):
            for z in xrange(len(grida[x])):
                if check(grida,x,z,row,col)>=3 and grida[x][z]!="E" and grida[x][z]!="S":
                    grida[x][z]="X"
                else:
                    continue
    return grida
grid_temp=grid[:]
print grid
grid_2=get_pos(grid_temp,row,col)
print grid

我想知道为什么网格实际上正在改变。

4

3 回答 3

10

您的网格变量是一个二维数组,即列表列表。当你这样做时,grid[:]你正在制作一个新的列表列表,但元素本身仍然是对同一迷宫行的引用。你想做一个深拷贝,例如模块中的deepcopy函数copy

于 2013-05-27T14:06:50.337 回答
1

简单的解决方案,使用copy模块而不是临时复制:

import copy
foo = copy.deepcopy(bar)

要回答您的问题,我认为为什么归结为您的代码中的以下位:

grida[x][y] = ...

虽然您的[:]副本仅复制一层深,但分配是两层深。

于 2013-05-27T14:09:36.380 回答
0

我的朋友,您在命名空间方面遇到了麻烦。 试试 new_array = old_array[:]。这会在数组中产生一个切片,但是因为冒号前后没有任何数字,所以它不会切断任何东西,但仍然会强制复制数组。

命名和绑定

名称指的是对象。名称由名称绑定操作引入。程序文本中每次出现的名称指的是在包含使用的最内层功能块中建立的该名称的绑定

是作为一个单元执行的一段 Python 程序文本。以下是块:模块、函数体和类定义。每个交互输入的命令都是一个块。脚本文件(作为标准输入提供给解释器或指定为解释器的命令行参数的文件)是一个代码块。脚本命令(在解释器命令行上使用“ -c ”选项指定的命令)是一个代码块。传递给内置函数“eval()”和“exec()”的字符串参数是一个代码块。

代码块在执行帧中执行。框架包含一些管理信息(用于调试)并确定代码块执行完成后在何处以及如何继续执行。

范围定义了名称在块中的可见性。如果在块中定义了局部变量,则其范围包括该块。如果定义出现在功能块中,则范围扩展到包含在定义块中的任何块,除非包含的块为名称引入了不同的绑定。类块中定义的名称范围仅限于类块;它没有扩展到方法的代码块——这包括理解和生成器表达式,因为它们是使用函数范围实现的。这意味着以下将失败:

A类:a = 42 b = list(a + i for i in range(10))

在代码块中使用名称时,将使用最近的封闭范围对其进行解析。对代码块可见的所有此类范围的集合称为代码块的环境

如果名称绑定在块中,则它是该块的局部变量,除非声明为“非本地”。如果名称绑定在模块级别,则它是一个全局变量。(模块代码块的变量是局部的和全局的。)如果一个变量在一个代码块中使用但没有在那里定义,它是一个自由变量

当根本找不到名称时,会引发“NameError”异常。如果名称引用了尚未绑定的局部变量,则会引发“UnboundLocalError”异常。“UnboundLocalError”是“NameError”的子类。

以下构造绑定名称:函数的形式参数、“import”语句、类和函数定义(这些在定义块中绑定类或函数名称)以及在赋值中作为标识符的目标、“for”循环头,或在“with”语句或“except”子句中的“as”之后。“from ... import *”形式的“import”语句绑定了导入模块中定义的所有名称,以下划线开头的名称除外。此表格只能在模块级别使用。

出现在“del”语句中的目标也被认为是为此目的绑定的(尽管实际语义是取消绑定名称)。

每个赋值或导入语句都出现在由类或函数定义定义的块内或模块级别(顶级代码块)。

如果名称绑定操作发生在代码块中的任何位置,则块中名称的所有使用都被视为对当前块的引用。如果在绑定之前在块中使用名称,这可能会导致错误。这个规则很微妙。Python 缺少声明,并允许名称绑定操作在代码块中的任何位置发生。代码块的局部变量可以通过扫描块的整个文本以进行名称绑定操作来确定。

如果“全局”语句出现在一个块中,则该语句中指定的名称的所有使用都指的是该名称在顶级命名空间中的绑定。通过搜索全局命名空间(即包含代码块的模块的命名空间)和内置命名空间(即模块“builtins”的命名空间)来解析顶级命名空间中的名称。首先搜索全局命名空间。如果在那里找不到名称,则搜索内置名称空间。全局语句必须在名称的所有使用之前。

与代码块执行相关的内置命名空间实际上是通过在其全局命名空间中查找名称“ builtins ”来找到的;这应该是字典或模块(在后一种情况下使用模块的字典)。默认情况下,在“ main ”模块中时,“ builtins ”为内置模块“builtins”;当在任何其他模块中时,“ builtins ”是“builtins”模块本身的字典的别名。“ builtins ”可以设置为用户创建的字典,以创建受限执行的弱形式。

CPython 实现细节:用户不应触摸“内置”;这严格来说是一个实现细节。想要覆盖内置命名空间中的值的用户应该“导入”“内置”模块并适当地修改其属性。

模块的命名空间是在第一次导入模块时自动创建的。脚本的主模块始终称为“ main ”。

“全局”语句与同一块中的名称绑定操作具有相同的范围。如果自由变量的最近封闭范围包含全局语句,则自由变量被视为全局变量。

类定义是可以使用和定义名称的可执行语句。这些引用遵循名称解析的正常规则。类定义的命名空间成为类的属性字典。在类范围内定义的名称在方法中不可见。

与动态特征的交互


当与包含自由变量的嵌套作用域结合使用时,有几种情况下 Python 语句是非法的。

如果在封闭范围内引用了变量,则删除该名称是非法的。编译时会报错。

如果在函数中使用通配符形式的 import --- "import *" --- 并且该函数包含或者是带有自由变量的嵌套块,编译器将引发“SyntaxError”。

“eval()”和“exec()”函数无法访问完整环境来解析名称。名称可以在调用者的本地和全局命名空间中解析。自由变量不在最近的封闭命名空间中解析,而是在全局命名空间中解析。[1] “exec()”和“eval()”函数具有可选参数来覆盖全局和局部命名空间。如果只指定了一个命名空间,则两者都使用。

相关帮助主题:全局、非本地、分配、删除、动态特征

于 2016-01-07T21:00:03.157 回答