每次运行函数时会创建一个frame,在frame环境下一条一条的运行python的字节码bytecode。frame是以栈为基础运行的,字节码或者从栈中弹出数据进行运算或者把数据添加到栈中。
每个函数都有一个code object,函数的__code__属性可以获得函数的code object
def func(a, b=1, /, *, c): pass code_obj = func.__code__ print(code_obj.co_code) # 字节码字符串 b'd\x00S\x00' print(code_obj.co_argcount) # 参数数量 2 print(code_obj.co_posonlyargcount) # 必须位置参数数量 2 print(code_obj.co_kwonlyargcount) # 必须关键字参数数量 1 import dis dis.dis(code_obj.co_code) # 0 LOAD_CONST 0 (0) # 2 RETURN_VALUE
print(code_obj.co_name) # func print(code_obj.co_filename) # xx.py print(code_obj.co_lnotab) # b'\x00\x01'
print(code_obj.co_flags) # 67 print(code_obj.co_stacksize) # 1
import dis def print_var(cobj): print(f"n locals: {cobj.co_nlocals}") print(f"varnames: {cobj.co_varnames}") print(f"cellvars: {cobj.co_cellvars}") print(f"freevars: {cobj.co_freevars}") print(f"names : {cobj.co_names}") print(f"consts : {cobj.co_consts}") class A: attr= 'class A' def A_f(): pass def g(): x = 1 dic = {} a = A() a.attr="B" def f(): y=3 dic['x']=1 return f g_code = g.__code__ f_code = g().__code__ dis.dis(g_code.co_code) print_var(g_code) print() dis.dis(f_code.co_code) print_var(f_code) """ 0 LOAD_CONST 1 (1) 2 STORE_FAST 0 (0) 4 BUILD_MAP 0 6 STORE_DEREF 0 (0) 8 LOAD_GLOBAL 0 (0) 10 CALL_FUNCTION 0 12 STORE_FAST 1 (1) 14 LOAD_CONST 2 (2) 16 LOAD_FAST 1 (1) 18 STORE_ATTR 1 (1) 20 LOAD_CLOSURE 0 (0) 22 BUILD_TUPLE 1 24 LOAD_CONST 3 (3) 26 LOAD_CONST 4 (4) 28 MAKE_FUNCTION 8 (closure) 30 STORE_FAST 2 (2) 32 LOAD_FAST 2 (2) 34 RETURN_VALUE n locals: 3 varnames: ('x', 'a', 'f') 局部变量名 cellvars: ('dic',) # dic被内部函数引用 freevars: () names : ('A', 'attr') # 其他名 consts : (None, 1, 'B', <code object f at 0x000001BFB302F7C0, file "d:\LinuxCcpp\web_framework\�½��ļ���\f_code_.py", line 42>, 'g.<locals>.f') 0 LOAD_CONST 1 (1) 2 STORE_FAST 0 (0) 4 LOAD_CONST 2 (2) 6 LOAD_DEREF 0 (0) 8 LOAD_CONST 3 (3) 10 STORE_SUBSCR 12 LOAD_CONST 0 (0) 14 RETURN_VALUE n locals: 1 varnames: ('y',) cellvars: () freevars: ('dic',) # 闭包引用的外部变量 names : () consts : (None, 3, 1, 'x') """