这是一种奇怪的行为。
试试这个:
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()
为什么列表不需要声明全局?它们会自动全球化吗?
我发现它真的很奇怪,我大部分时间都使用列表,我甚至根本不使用全球它们作为全球......
答案 0 :(得分:13)
它不是自动全局的。
然而,rep_i=1
和rep_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
。