Python 程序由代码块组成,代码块可以是模块、函数或类,也可以是脚本文件,还可以是python - c 'string'
和exec ('string')
、eval ('string')
中字符串的内容。
两种方法:
fun.__code__
获取函数 fun 主体的代码对象
compile('source code','','exec')
获取代码块 source code 的代码对象
fun(a,b)
,它完成简单的加法运算。def fun(a,b):
return a+b
for attr in dir(fun.fun.__code__):
if attr.startswith('co_'):
print('{attr}:\t{attrs}'.format(
attrs=getattr(attr=attr,fun.fun.__code__, attr)))
co_argcount: 2
co_cellvars: ()
co_code: b'|\x00|\x01\x17\x00S\x00'
co_consts: (None,)
co_filename: G:\pythonCodeStudy\manuscript\0 bytecode\fun.py
co_firstlineno: 1
co_flags: 67
co_freevars: ()
co_kwonlyargcount: 0
co_lnotab: b'\x00\x01'
co_name: fun
co_names: ()
co_nlocals: 2
co_posonlyargcount: 0
co_stacksize: 2
co_varnames: ('a', 'b')
Python虚拟机是基于栈的机器,每步函数调用产生栈帧(stack frame)。每个栈帧包含计算栈和块栈。所有参数压入计算栈,调用时弹栈,计算后弹出结果,结束本栈帧。
def outer(o1, o2='o2'):
e = 'enclose'
def inner(i1, i2='i2'):
print(e)
return e
return inner
print(outer.__code__.co_cellvars)
print(outer('i1').__code__.co_freevars)
('e',)
('e',)
co_cellvars 是被内部嵌套块(函数)引用的变量组成的元组。外部函数创建特殊的 cell 对象存储该变量,cell 对象的生存周期超过了定义它的外部函数。这句话理解就是:外部变量执行完之后,清理现场,它的变量都消失了,但 cell 对象不消失,仍然存在。这也就是所谓 * cell 变量*
co_freevars 就块内使用,但是并未在该块内定义的变量(不含全局变量、内置变量)。也就是当前块(函数) 引用的外部 cell 变量 组成的元组,和上个 co_cellvars 是相对的概念
外部变量 outer 作用域里,创建了变量 e 以及变量 inner (函数)。
因为嵌套函数 inner 使用了外部变量 e ,所以在 outer 函数里, e 是作为 cell 变量,绑定到特殊的 cell 对象里。
这个特殊的 cell 对象和 inner 绑定在了一起,这样 outer 作用域消失的时候, inner 内部借由 cell 对象访问到了 e 这个变量,它对 inner 函数来说是(来自 cell 对象的)自由变量。
co_code : b '|\ x00 |\ x01 \ x17 \ x00S \ x00 '
。co_code [0]
表示第一个操作码|
,这是 ASCII 码 124 表示的字符,在 include/opcode.h 中,可以看到 124 是 LOAD_FAST 操作码,这是对局部变量列表进行的加载操作。其它类似的:比如 LOAD_CONST 就是对字面常量列表操作,LOAD_GLOBAL 是对全局变量操作。co_code[1]
为 0x00 。dis.dis(fun)
来反汇编代码,得到字节码如下。 2 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_ADD
6 RETURN_VALUE
return a+b
这一条。dis.dis(fun)
指令,这里的 fun 是函数。print(dis.dis(compile('def fun(a,b): return a+b', '', 'exec')))
,输出如下。可见此时的函数只是一个代码对象,作为常量载入,MAKE_FUNCTION 后,赋值给 fun 局部变量。 1 0 LOAD_CONST 0 (<code object fun at 0x00A67B18, file
'', line 1>)
2 LOAD_CONST 1 ('fun')
4 MAKE_FUNCTION 0
6 STORE_NAME 0 (fun)
8 LOAD_CONST 2 (None)
10 RETURN_VALUE
作者:巩庆奎,大奎,对计算机、电子信息工程感兴趣。gongqingkui at 126.com
联系客服