Python 更改列表元素与更改列表本身

Python 更改列表元素与更改列表本身,python,variables,scope,Python,Variables,Scope,我有一个关于变量的名称范围的问题,我试图在这里找到答案,我得到了一个类似的答案,但仍然有点困惑 因此,代码如下: position = [50, 50] # Handler for timer def tick(): x = random.randrange(0, width) y = random.randrange(0, height) position[0] = x position[1] = y 在这里,为什么我不需要添加“全局位置”来更改可变位置的

我有一个关于变量的名称范围的问题,我试图在这里找到答案,我得到了一个类似的答案,但仍然有点困惑

因此,代码如下:

position = [50, 50]

# Handler for timer
def tick():
    x = random.randrange(0, width)
    y = random.randrange(0, height)
    position[0] = x
    position[1] = y

在这里,为什么我不需要添加“全局位置”来更改可变位置的元素

只有在分配全局位置变量以引用新列表时才需要添加全局位置(如果没有全局声明,位置将写入函数的局部变量中)

在您的情况下,您所做的只是查找全局变量位置,以找到它所引用的列表。然后,您将更新该列表

下面是一个显示所有变体的列表(分配给本地、分配给全局、更新全局引用的列表)

另外,请看一看Ned Batchelder的文章,其中充分解释了python的对象传递机制。

From-

如果某个变量在代码块中使用,但未在代码块中定义,则该变量为自由变量

从—

global语句是一个声明,用于保存整个当前代码块。这意味着列出的标识符将被解释为全局标识符。如果没有全局变量,就不可能分配给全局变量,,尽管自由变量可能引用全局变量而不声明为全局变量。

(强调矿山)

当你这样做的时候-

position[0] = <something>
position[0] = <something>
您将得到
namererror
-

>>> position[0] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'position' is not defined
>位置[0]=1
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
名称错误:未定义名称“位置”
这就是为什么,即使您执行了
position[0]=
,它仍然是一个自由变量,因为它没有在块中定义,因此它被视为全局变量


更新

更多信息,当你这样做-

position[0] = <something>
position[0] = <something>
位置[0]=

这不是一个,实际上是一个。

您需要应用两个概念来理解代码

  • Python对象模型
  • 范围界定
首先是范围规则:

以下是变量作用域规则的层次结构

  • 局部作用域-函数内部
  • 封闭-在任何或所有封闭函数内
  • 全局-顶级模块(文件)
  • 内置-正在导入的任何内置模块
  • Python对象模型:

    在Python中,一切都是对象。 当声明一个变量时,比如说
    x=1000
    ,将发生以下步骤

    • 创建值为1000的int对象
    • 已创建对象引用
      x
    • x
      指向该整数对象
    现在,当在
    tick()
    内执行语句
    position[0]=x
    时,该语句不具有仅初始化部分的赋值。由于
    位置
    未在函数范围内定义,因此它会按作用域规则的层次结构顺序进行查找-封闭范围(父函数)后跟模块范围(文件),后跟内置模块。在这里,它在全局范围内找到变量并更新它

    如果您的语句是
    position=[100100]
    ,则将创建一个新的列表对象,并在tick()函数的作用域内创建新的对象引用并执行赋值


    若有
    global position
    语句,它会告诉Python全局范围内的变量和局部范围内的变量相同。随后是
    position=[100100]
    创建一个列表对象
    [100100]
    ,并将其全局变量
    position
    链接到新的列表对象。

    那么您的意思是position元素会自动更新,而无需将其声明为全局?我有点难以接受这个概念…是的。这样想吧。假设您有一个名为position的全局变量,它是与数据库的连接。您可以在不使用全局声明的情况下查找该变量(因为没有同名的局部变量)。然后可以使用该连接修改数据库,但不更改连接本身。什么时候需要全球宣言?仅当您正在为位置分配新连接时。在第一种情况下,位置保持不变,数据库更改。在第二种情况下,position被更改为另一个连接。谢谢,但是我怎么知道我最初提供的cod是哪种情况的呢?那么你的意思是position的元素会自动更新,而无需声明为global?我有点难以接受这个概念…谢谢,但我还是有点困惑,所以你说当我做“位置[0]=x”时,对象位置在全局范围内是可用的,我同意这一点,但是当我做“位置=[100100]”时,对象位置在全局范围内不是仍然可用吗?它为什么会创建一个新对象?@Enkri\ux,当执行
    position=[100100]
    时,初始化和赋值都会发生。因此,位置在局部范围内定义,并发生赋值。当执行
    位置[0]=x
    时,仅发生赋值。它不进行初始化,而是按照作用域规则的层次结构开始搜索,在全局范围内找到匹配项并进行更新。我更新了我的答案以反映同样的情况,