作为初学者,简单总结自己对Python命名空间(namespace)和作用域(scope)的认识。
Python在名称空间搜寻变量和函数的顺序可以认为是:
函数内部 -> (嵌套)父函数内部 -> 模块内部 -> built_in内置模块
1. 函数内部(local)
简单举例说明:
x = 123 def func(): x = 456 print 'inner x =', x func() print 'outer x =', x
输出:
inner x = 456 outer x = 123
模块级变量x的值是123,而在函数func内部,local变量x的值是456。可以看到,函数是没有改变外部x的值的。
2. 父函数内部
x = 123 def func(): x = 456 print 'inner x =', x def child_func(): print 'x from parent function =', x child_func() func() print 'outer x =', x
输出为:
inner x = 456 x from parent function = 456 outer x = 123
child_func是func的嵌套函数,它的x值,来自其父函数func内部,而非模块级变量。
3.模块内部
模块内也就是我们常说的全局变量。
x = 123 def func(): print 'inner x =', x func() print 'outer x =', x
输出为:
inner x = 123 outer x = 123
func内部没有命名变量x,print语句使用的x来自函数外的模块级变量x。
4. Built_in内置模块
print abs(-123) def abs(x): return x + 100 print abs(-123)
输出:
123 -23
这里第一次调用的abs函数来自__builtins__。第二次调用来自模块内部。
5. 神奇的global关键字
global用于向函数中引入全局变量,这个关键字是非常神奇的。
x = 123 def func(): x = 333 if False: global x print 'inner x = ', x func() print 'outer x = ', x
按照一般的理解,global x声明位于x变量使用之后,并且,它永远不可能得到执行,那么前面x = 333使用的是local变量才是。但最终的运行结果很出乎意料:
SyntaxWarning: name 'x' is assigned to before global declaration global x inner x = 333 outer x = 333
Python会给出一个警告,但打印出的结果却显示,函数中使用了模块级变量(全局变量)x。这说明,只要有global语句在源代码中,不管这条语句是否执行,也不管你把这句代码放在函数的哪个位置,python解释器都将使用全局变量。文档中提到:
the language definition is evolving towards static name resolution, at “compile” time, so don’t rely on dynamic name resolution!
6. 被调用函数无法共享调用函数的命名空间
def caller(): x = 123 callee() def callee(): print 'callee inner x', x caller()
执行时将出现NameError: global name ‘x’ is not defined
你好,怎么才能避免那个global warning