为什么列表没有任何理由变化?

时间:2013-05-27 14:02:47

标签: python

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

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

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

3 个答案:

答案 0 :(得分:10)

您的网格变量是2D数组,即列表列表。当您执行grid[:]时,您正在创建一个新的列表列表,但元素本身仍然是对同一迷宫行的引用。你想做一个深度复制,例如deepcopy模块中的copy函数。

答案 1 :(得分:1)

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

import copy
foo = copy.deepcopy(bar)

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

grida[x][y] = ...

虽然您的[:]副本仅复制一个级别,但分配深度为两级。

答案 2 :(得分:0)

您,我的朋友,在使用命名空间时遇到了问题。 尝试new_array = old_array [:]。 这会导致数组中的切片,但由于冒号之前或之后没有任何数字,因此它不会切断任何数字,但仍会强制复制数组。

命名和绑定

名称指的是对象。名称通过名称绑定引入 操作。程序文本中每次出现的名称都是指 在最里面的功能块中建立的该名称的绑定 包含用途。

是一段Python程序文本,作为一个执行 单元。以下是块:模块,函数体和类 定义。交互式输入的每个命令都是一个块。一个脚本 file(作为解释器的标准输入或指定的文件) 作为解释器的命令行参数)是一个代码块。一个 script命令(在解释器命令行上指定的命令 使用&#39; -c &#39; option)是一个代码块。传递的字符串参数 到内置函数&#34; eval()&#34;和&#34; exec()&#34;是一个代码块。

代码块在执行帧中执行。一个框架包含 一些管理信息(用于调试)和确定 代码块执行后执行继续的位置和方式 完成。

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

A类:        a = 42        b = list(范围(10)中i的a + i)

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

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

当根本找不到名字时,&#34; NameError&#34;提出异常。 如果名称引用了尚未绑定的局部变量,则为 &#34; UnboundLocalError&#34;提出异常。 &#34; UnboundLocalError&#34;是一个 &#34; NameError&#34;。

的子类

以下构造绑定名称:形式参数到函数, &#34;进口&#34;语句,类和函数定义(这些绑定 定义块中的类或函数名称)和目标 标识符如果出现在作业中,&#34;对于&#34;循环标题,或之后 &#34;如&#34;在&#34;与&#34;声明或&#34;除了&#34;条款。 &#34;导入&#34;声明 形式&#34;来自... import *&#34;绑定在中定义的所有名称 导入的模块,除了以下划线开头的模块。这个表格 只能在模块级别使用。

目标发生在&#34; del&#34;声明也被视为必然 这个目的(虽然实际的语义是取消绑定名称)。

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

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

如果&#34;全球&#34;语句发生在一个块内,所有使用的名称 在语句中指定的是指该名称的绑定 顶级命名空间。名称在顶级名称空间中解析 搜索全局命名空间,即模块的命名空间 包含代码块和内置命名空间,命名空间 该模块&#34; builtins&#34;。首先搜索全局命名空间。如果 在那里找不到名称,搜索内置命名空间。该 全局声明必须在名称的所有使用之前。

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

CPython实施细节:用户不应该触摸 &#34;的建宏&#34 ;;它严格来说是一个实现细节。用户 想要覆盖内置命名空间中的值应该&#34; import&#34; &#34;内置&#34;模块并适当地修改其属性。

第一次自动创建模块的命名空间 模块已导入。始终调用脚本的主模块 &#34; 主要&#34;

&#34;全球&#34;语句与名称绑定操作具有相同的范围 在同一个街区。如果是最近的自由变量的封闭范围 包含一个全局语句,将自由变量视为全局变量。

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

与动态功能的互动

在某些情况下,Python语句在使用时是非法的 与包含自由变量的嵌套作用域一起使用。

如果在封闭范围中引用变量,则非法 删除名称。编译时将报告错误。

如果是外卡形式的导入---&#34;导入*&#34; ---用于 函数和函数包含或是一个带有free的嵌套块 变量,编译器将引发&#34; SyntaxError&#34;。

&#34; eval()&#34;和&#34; exec()&#34;函数无权访问 解决名称的环境。名称可以在当地解决 和调用者的全局命名空间。自由变量未解决 在最近的封闭命名空间中,但在全局命名空间中。 [1] &#34; exec()&#34;和&#34; eval()&#34;函数有可选参数 覆盖全局和本地名称空间。如果只有一个名称空间 指定,它用于两者。

相关帮助主题:全局,非本地,分配,删除,动态功能