编译原理 python_Python局部变量编译原理

因此,Python将始终将每个函数中的每个名称分类为本地名称,非本地名称或全局名称.这些名称范围是独占的;在每个函数内(嵌套函数中的名称都有自己的命名范围),每个名称只能属于这些类别中的一个.

当Python编译这段代码时:

def fun():

if False:

x=3

它将产生一个抽象语法树,如:

FunctionDef(

name='fun',

args=arguments(...), b

body=[

If(test=NameConstant(value=False),

body=[

Assign(targets=[Name(id='x', ctx=Store())], value=Num(n=3))

],

orelse=[])

]

)

(为简洁起见省略了一些东西).现在,当这个抽象语法树被编译成代码时,Python将扫描所有名称节点.如果存在任何名称节点,使用ctx = Store(),则该名称被认为是封闭的FunctionDef的本地名称(如果有),除非在同一函数定义中覆盖全局(即全局x)或非本地(非本地x)语句.

ctx = Store()将主要发生在赋值的左侧使用有问题的名称,或者作为for循环中的迭代变量时.

现在,当Python将其编译为字节码时,生成的字节码就是

>>> dis.dis(fun)

4 0 LOAD_GLOBAL 0 (print)

3 LOAD_FAST 0 (x)

6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)

9 POP_TOP

10 LOAD_CONST 0 (None)

13 RETURN_VALUE

优化器完全删除了if语句;但是由于变量已经标记为函数的本地变量,因此LOAD_FAST用于x,这将导致x从局部变量和局部变量访问.由于尚未设置x,因此抛出UnboundLocalError.另一方面,名称print从未被赋值,因此被认为是此函数中的全局名称,因此其值使用LOAD_GLOBAL加载.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值