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

时间:2011-06-13 10:57:14

标签: python list global python-2.7

这是一种奇怪的行为。

试试这个:

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()

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

我发现它真的很奇怪,我大部分时间都使用列表,我甚至根本不使用全球它们作为全球......

5 个答案:

答案 0 :(得分:13)

它不是自动全局的。

然而,rep_i=1rep_lst[0]=1之间存在差异 - 前者重新命名rep_i,因此需要global来防止创建相同的本地广告位名称。在后一种情况下,您只是修改现有的全局对象,它通过常规名称查找找到(更改列表条目就像调用列表中的成员函数,它不是名称重新绑定)。

要测试一下,请尝试在rep_lst=[]中指定test2(即将其设置为新列表)。除非您声明rep_lst global,否则效果将不会在test2之外显示,因为会创建同名的本地广告位并隐藏全局广告位。

答案 1 :(得分:5)

如果要分配全局名称,则只需使用global。如果没有global,则分配会创建新的本地。

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

答案 2 :(得分:3)

python中有一个名为UnboundLocalError的错误,它经常让新手感到困惑。令人困惑的是:未来分配确实改变查找变量的方式。

当解释器第一次看到变量名时,它会向前看当前代码块的结尾,如果在同一代码块中的任何地方都没有赋值,那么解释器会认为它是全局的。但是,如果您这样做,那么它将被视为本地,并且在分配之前对它的任何引用都会生成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

答案 3 :(得分:2)

如果您已在rep_lst内为test2分配了一个新值(不仅仅是其中一个元素,就像您所做的那样),如果没有global标记,它将无效。在Python中,如果不在函数内部分配变量,它将在更多全局范围内查找该变量,直到找到它为止。

例如,在此代码段中,我在example()的全局和内部定义列表。由于example()中的变量在范围上比example2()更接近全局变量,因此它将被使用。

x = ["out"]

def example():
    x = ["in"]
    def example2():
        print x # will print ["in"]

这与列表无关,而是Python中任何变量的行为。

答案 4 :(得分:2)

以下是一个示例,该示例演示了子例程中的非list / dict变量,并且正如所有人所说,问题是原始代码中rebinding的行为样品:

x = 1
def test():
    y = x + 1
    print y
test()

尽管2未被声明为全局,但您会看到这打印出x