Python函数作用域名字空间,locals的原理。

最近在回看《Python学习笔记》看到函数这一章节,书中P153页。

书中介绍了函数的每次调用,都会新建栈帧,用于局部变量和执行过程的存储。

等执行结束,栈帧内存被回收,同时释放相关对象。

以字典实现的名字空间,虽然灵活,但存在访问效率低下等问题。这对于使用频率较低的模块名字空间尚可,可对于有性能要求的函数调用,显然就是瓶颈所在。

为此,解释器划出专门的内存空间,用效率最快的数组代替字典。在函数指令执行前,先将包含参数在内的所有局部变量,以及要使用的外部变量复制(指针)到该数组。

基于作用域不同,此内存区域可简单分为两部分:FAST和DEREF

 

如此,操作指令只需要索引既可理解读取或存储目标对象,这远比哈希查找过程高效很多。从dis可以看出来,load读取操作的都是索引。

 

空间名字

那locals函数返回的东西是哪里来的,locals函数产生的字典是按需延迟创建,并从FAST区域复制相关信息得来的。

def test():
    x = 100
    locals()['x'] = 999

    print('fast.x =', x)
    print('local.x =', locals()['x'])


test()

  输出

fast.x = 100
local.x = 100

从输出就可以看出来,locals并不能改变函数局部作用域的命名空间,这个一个单线的操作,每次都会从函数的命名空间的元祖生成一个字典,

可能是为了对应globals吧,也可能为了格式的统一显式。

 

这个Python的底层还真的有意思。

 

posted @ 2021-01-28 15:32  就是想学习  阅读(129)  评论(0编辑  收藏  举报