Python函数调用和栈帧原理详解

2023-04-11 00:00:00 函数 调用 详解

在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()得到局部变量xy的值,这是一个字典类型。在该字典中,键是变量的名称,值是变量的值。在执行过程中使用globals()可以访问全局变量。在本例中,globals()["__name__"]访问了当前模块的名称。

总结

本文介绍了Python函数调用和栈帧原理。每个函数的调用都会创建一个栈帧,栈帧保存了函数的局部变量、参数、返回地址和其他必要信息。栈帧构成了函数调用的堆栈,也被称为调用栈。在函数执行完成后,栈帧被弹出,控制流回到调用位置。此外,还有一些内置函数可以访问局部变量和全局变量。

相关文章