作用域测试例子:
>>> a = 10 >>> def test(): ... a = 20 ... print a ... >>> a 10 >>> test() 20 >>> a #执行test之后,a的值还是10,没有变 10
这里涉及作用域问题。
作用域
函数形参和内部变量都存储在locals名字空间中。
>>> def test(a,*args,**kwargs): ... s = "Hello test!" ... print locals() ... >>> test(1,"a","b",x=10,y="hi") {'a': 1, 's': 'Hello test!', 'args': ('a', 'b'), 'kwargs': {'y': 'hi', 'x': 10}}
除非使用global、nolocal特别声明,否则在函数内部使用赋值语句,总是在locals名字空间中新建一个对象关联。注意:赋值是指名字指向新的对象,而非通过名字改变对象状态。
回过头来看看上面的例子:
>>> a = 10 >>> def test(): ... a = 20 ... print a ... >>> a 10 >>> test() #两个x指向不同的对象 20 >>> a #外部变量没有被修改 10
如果仅仅是引用外部变量,那么按LEGB顺序在不同作用域查找该名字。
名字查找顺序: locals ->enclosing function ->global ->__builtins__
>>> a = 10 >>> locals() {'a': 10, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'test': <function test at 0x7f1ce69ff578>, '__name__': '__main__', '__doc__': None} >>> >>> def test(): ... a = 20 ... print locals() ... print globals() ... >>> globals() #和locals相同 {'a': 10, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'test': <function test at 0x7f1ce69ff5f0>, '__name__': '__main__', '__doc__': None} >>> test() {'a': 20} #locals只有形参 {'a': 10, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'test': <function test at 0x7f1ce69ff5f0>, '__name__': '__main__', '__doc__': None}
*locals:函数内部名字空间,包括局部变量和形参
*enclosing function:外部嵌套函数的名字空间
*globals:函数定义所在模块的名字空间
*__builtins__:内置模块的名字空间
如果想将外部名字关联到一个新对象,就需要使用global关键字,指明要修改的是globals空间。
>>> a = 10 >>> def test(): ... global a #声明a,b是globals名字空间中的 ... global b ... a = 20 ... b = 30 ... print "a in test= ",a ... print "b in test=",b ... >>> globals() {'a': 10, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'test': <function test at 0x7f1ce69ff2a8>, '__name__': '__main__', '__doc__': None} >>> test() a in test= 20 b in test= 30 >>> globals() {'a': 20, 'b': 30, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'test': <function test at 0x7f1ce69ff2a8>, '__name__': '__main__', '__doc__': None}
>>> if True: ... a = 10 ... >>> globals() {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'a': 10, '__package__': None} >>> if False: ... b = 10 ... >>> globals() {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'a': 10, '__package__': None} >>> def test(): ... KeyboardInterrupt >>> b Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'b' is not defined
因为b变量对应的分支是False,不会产生b变量,而a不同,a已经在globals存在,故使用a没有问题,而使用b会出现错误。