Python函数调用和栈帧原理详解
在Python中,每当一个函数被调用,就会创建一个栈帧(stack frame),也被称为活动记录(activation record),用于存储函数的局部变量、参数、返回地址和其他信息。栈帧构成了函数调用的堆栈,也被称为调用栈。
下面通过一个例子加深理解。
示例代码:
def func1(): x = 1 func2() print(x) def func2(): y = 2 func3() print(y) def func3(): z = 3 print(z) func1()
在执行过程中,先调用func1()
函数,那么就会创建一个栈帧来存储func1()
函数的局部变量和参数,同时保存当前的返回地址。局部变量x
被赋值为1,然后函数调用栈上面压入func2()
的栈帧,现在调用栈上有func2()
和func1()
的栈帧,func2()
的栈帧保存了局部变量y
和返回地址。func3()
被调用后再次压入栈帧。现在调用栈上是func3()
、func2()
和func1()
的栈帧。
此时,从func3()
函数返回,它的栈帧弹出了,控制流回到func2()
。这里的局部变量y
仍然存在于func2()
的栈帧中,并且仍然可以访问。在func2()
函数余下的部分执行完成后,func2()
的栈帧也弹出了,控制流回到func1()
。同样,func1()
的局部变量x
仍然可以访问,输出1。
最终,func1()
的栈帧被弹出,程序结束。
在Python中,所有东西都被视为对象,栈帧也不例外。每个栈帧都是一个对象,由frame
类来实现。通过locals()
可以访问到函数的局部变量。通过globals()
可以访问全局变量。
示例代码:
def func(): x = 1 y = "pidancode.com" print(locals()) print(globals()["__name__"]) func()
输出结果:
{'y': 'pidancode.com', 'x': 1} __main__
在func()
函数内部,通过locals()
得到局部变量x
和y
的值,这是一个字典类型。在该字典中,键是变量的名称,值是变量的值。在执行过程中使用globals()
可以访问全局变量。在本例中,globals()["__name__"]
访问了当前模块的名称。
总结
本文介绍了Python函数调用和栈帧原理。每个函数的调用都会创建一个栈帧,栈帧保存了函数的局部变量、参数、返回地址和其他必要信息。栈帧构成了函数调用的堆栈,也被称为调用栈。在函数执行完成后,栈帧被弹出,控制流回到调用位置。此外,还有一些内置函数可以访问局部变量和全局变量。
相关文章