手写 Python 虚拟机
海纳
华为资深编译专家,原 Huawei JDK 团队负责人
1047 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已更新 13 讲/共 28 讲
导学|直播加餐:三小时掌握C++ (2讲)
手写 Python 虚拟机
15
15
1.0x
00:00/00:00
登录|注册

10|变量的作用域:哪些复杂规则是因函数而产生的?

你好,我是海纳。
上一节课我们实现了函数的基本功能,可以调用一个不带参数的函数,也可以正常地得到函数的返回值。引入函数以后,就有了新的命名空间(namespace),简单说就是函数内部定义的变量,在函数外部是访问不到的,这就产生了变量的作用域的问题。这一节课,我们就来实现函数的作用域。

变量的作用规则

在 Python 语言中,主要有四种类型的变量,按照作用域从小到大排列,分别是局部变量(Local)、闭包变量(Enclosing)、全局变量(Global)和内建变量(Builtin)。
例如以下三个例子:
global x
x = 0
def foo():
x = 2
def bar():
print(x)
def goo():
x = 3
print(x)
return bar, goo
def func():
global x
x = 1
func()
print(x) #this is 1
bar, goo = foo()
bar() # this is 2
goo() # this is 3
代码的注释里已经把结果标明了。
第 2 行定义了全局变量 x,但是在 goo 方法里,又定义了一个局部变量 x,那么第 11 行要打印 x 的值的时候,首先就会去局部变量表里查找。在 goo 方法里首先查到的是第 10 行定义的局部变量,所以这里就会打印 3。也就是说局部变量对全部变量 x 造成了覆盖。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

1. Python中的变量作用域包括局部变量、闭包变量、全局变量和内建变量,按照LEGB规则进行查找。 2. 全局变量可以通过global关键字在函数内部进行修改,而闭包变量可以在函数内部访问外部函数的局部变量。 3. Python 2和Python 3版本在处理内建变量时有所不同,Python 3中的print函数已经变成了内建函数。 4. 实现全局变量功能需要在FrameObject中添加全局变量表,并且需要考虑跨文件的全局变量是如何工作的。 5. 虚拟机应该将FrameObject中的全局变量表打包进FunctionObject,以确保函数对象所使用的全局变量表是定义该函数时所在文件的全局变量表。 6. 为了实现这一功能,需要为FunctionObject引入一个变量表,并在创建函数对象时将当前栈帧的全局变量表传递给FunctionObject。 7. 设计合理的全局变量表机制可以保证在文件的模块中,全局变量表和局部变量是相同的,同时也保证了在同一个文件中定义的函数所使用的全局变量表是同一个。 8. LOAD_GLOBAL 和 STORE_GLOBAL 指令用于操作全局变量表,而LOAD_NAME指令依赖于LEGB规则,需要在全局变量表查找失败后继续在内建变量表中查找。 9. 内建变量表在虚拟机的初始化阶段放置内建变量,LOAD_NAME指令需要增加逻辑以在内建变量表中查找变量。 10. 引入函数后,产生了全局变量、局部变量、闭包变量、内建变量等概念,按照LEGB规则访问变量,并添加了访问全局变量的机制,修改了LOAD_NAME的查找逻辑,并准备好了内建变量表。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手写 Python 虚拟机》
新⼈⾸单¥59
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部