变量名的查找规则
Python 在查找变量或者“名称”时,是按照 LEGB 规则查找的:Local-->Enclosed-->Global-->Built in
L —— Local(function);本地作用域、局部作用域的命名空间。在函数被调用时创建、调用结束消亡
E —— Enclosing function locals;嵌套函数中外层函数的命名空间,实现了闭包(closure)
G —— Global(module);函数定义所在模块(文件)的名称空间。全局作用域,模块被import导入的时候创建,解释器退出时消亡
B —— Builtin(Python);Python内置模块的名称空间。从Python解释器启动时创建到解释器退出时消亡。
总而言之,就是从本地向外一层层的查找变量或名称。注意nonlocal的时候不能用到最外层函数
函数的执行过程
http://pythontutor.com/visualize.html#mode=edit
def foo(a, b=1):
print("foo", a, b)
def foo1(c):
bar(c)
print("foo1", c)
def bar(d):
print("bar", d)
def main():
print("main")
foo(2, 4)
foo1(10)
print("main ended")
main()
运行结果
main
foo2 4bar10foo110main ended
上面函数的执行过程
1、在全局帧中生成foo、foo1、bar、main这些函数对象
2、main函数开始调用
3、main函数根据LEGB原则找到内建函数print压栈,将print的参数压栈,调用函数print后将其弹出栈顶,main函数保存结果
4、main函数在全局作用域查找到函数foo压栈,将参数常量2,4压栈,调用函数foo并创建栈帧。将print函数压栈,将变量a和b压栈,调用函数后弹出栈顶,返回返回值。
5、main函数在全局作用域找到函数foo1压栈,将常量10压栈,调用foo1函数并创建栈帧。bar函数压栈,变量c压栈,调用bar函数并创建栈帧。bar函数中的print函数调用完成后返回。
6、foo1恢复,执行print后返回。main函数中foo1调用结束弹出栈顶,main函数执行print函数调用,弹出栈顶
7、main函数返回
在pycharm中通过断点查看