在Python中,为什么list[]自动是全局的?
这真是个奇怪的情况。
试试这个:
rep_i=0
print "rep_i is" , rep_i
def test():
global rep_i #without Global this gives error but list , dict , and others don't
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 个回答
在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
你只有在给全局变量赋值的时候才需要用到 global
。如果不使用 global
,那么赋值就会在本地创建一个新的变量。
对于列表来说,global
并没有什么特别的作用——它只是影响变量的作用范围和名称解析。
这并不是自动变成全局的。
不过,rep_i=1
和 rep_lst[0]=1
之间是有区别的——前者是重新绑定了名字 rep_i
,所以需要用到 global
来防止创建一个同名的局部变量。而后者只是修改了一个已经存在的全局对象,这个对象通过正常的名字查找就能找到(修改列表中的一个元素就像是在调用列表的一个成员函数,这并不是重新绑定名字)。
想测试一下的话,可以在 test2
里尝试赋值 rep_lst=[]
(也就是把它设置成一个新的列表)。除非你声明 rep_lst
为 global
,否则在 test2
外面是看不到效果的,因为这时会创建一个同名的局部变量,遮住了全局变量。