在Python中,为什么list[]是自动全局的?

2024-04-20 10:31:53 发布

您现在位置:Python中文网/ 问答频道 /正文

这是一种奇怪的行为。

试试这个:

rep_i=0
print "rep_i is" , rep_i
def test():
  global rep_i #without Global this gives error but list , dict , and others dont
  if rep_i==0:
    print "Testing Integer %s" % rep_i
    rep_i=1
  return "Done"

rep_lst=[1,2,3]


def test2():
  if rep_lst[0]==1:
    print "Testing List %s" % rep_lst
  return "Done"


if __name__=="__main__":
  test()
  test2()

为什么列表不需要声明全局?它们是自动全球化的吗?

我发现它真的很wierd,我使用列表的大部分时间,我甚至没有使用全球作为我们的全球。。。。。


Tags: test列表returnifisdeftestingglobal
3条回答

python中有一个名为UnboundLocalError的错误,它常常使新用户感到困惑。令人困惑的是:future赋值会改变查找变量的方式。

当解释器第一次看到变量名时,它会向前看到当前代码块的末尾,如果在同一代码块中的任何地方都没有对它的赋值,解释器会认为它是全局的。但是,如果您这样做了,那么它被认为是本地的,并且在赋值之前对它的任何引用都会生成一个UnboundLocalError。这就是你犯的错误。这就是为什么您需要声明global rep_i。如果你不指定rep_i,你就不需要这一行。

而且,这与变量类型无关。此外,将一个项分配或附加到列表(您可能打算这样做,但没有这样做)并不是列表本身的分配,它实质上是对列表对象调用一个方法,这与分配不同:分配创建一个新对象(可能在已经存在的名称下),而操作列表只会更改一个现有的列表。 您可以尝试:

In [1]: # It won't work with small integers, as they are cached singletons in CPython

In [2]: a = 123123

In [3]: id (a)
Out[3]: 9116848

In [4]: a = 123123

In [5]: id(a)
Out[5]: 9116740

In [6]: # See, it changed

In [7]: # Now with lists

In [8]: l = [1,2,3]

In [9]: id(l)
Out[9]: 19885792

In [10]: l[1] = 2

In [11]: id(l)
Out[11]: 19885792

In [12]: # See, it is the same

In [13]: # But if i reassign the list, even to the same value

In [14]: l = [2,2,3]

In [15]: id(l)
Out[15]: 19884272

它不是自动全球化的。

但是,rep_i=1rep_lst[0]=1之间有区别——前者重新绑定名称rep_i,因此需要global来防止创建同名的本地插槽。在后一种情况下,您只需修改一个现有的全局对象,该对象是通过常规的名称查找找到的(更改列表项就像调用列表上的成员函数一样,它不是名称重新绑定)。

若要测试它,请尝试在test2中分配rep_lst=[](即将其设置为新列表)。除非声明rep_lstglobal,否则效果在test2外部将不可见,因为将创建同名的本地插槽,并将全局插槽隐藏起来。

如果要分配给全局名称,只需要使用global。如果没有global,赋值将创建一个新的本地。

对于global如何应用于列表,没有什么特别之处-global只是影响范围和名称解析。

相关问题 更多 >