全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 10 分钟 ✍️ juanwangdev

Python代码对象与字节码

Python代码编译为Code Object后由虚拟机执行,理解这一过程有助于性能优化和代码分析。

Code Object 结构

Python
def example(a, b=10, *args, **kwargs):
    "示例函数"
    local = a + b
    for arg in args:
        local += arg
    return local

code = example.__code__

# Code Object 属性
print(f"名称: {code.co_name}")               # 'example'
print(f"参数数量: {code.co_argcount}")        # 2(不含*args, **kwargs)
print(f"位置参数: {code.co_posonlyargcount}") # 0
print(f"关键字参数: {code.co_kwonlyargcount}")# 0
print(f"局部变量: {code.co_varnames}")        # ('a', 'b', 'args', 'kwargs', 'local', 'arg')
print(f"自由变量: {code.co_freevars}")        # ()(无闭包)
print(f"常量: {code.co_consts}")              # (None, 10)
print(f"名称: {code.co_names}")               # ()(无全局名)
print(f"文件名: {code.co_filename}")
print(f"首行号: {code.co_firstlineno}")       # 函数定义行号
print(f"标志: {code.co_flags}")               # 位标志
属性说明
co_name代码块名称
co_filename源文件路径
co_firstlineno代码块起始行号
co_argcount位置参数数量
co_varnames局部变量名元组
co_consts常量元组
co_names全局/属性名元组
co_freevars自由变量(闭包捕获)
co_code字节码字节串
co_lnotab行号映射表(旧版)
co_lines行迭代器(Python 3.10+)

compile 函数

Python
# compile(source, filename, mode, flags=0)
source = "
def greet(name):
    return f"Hello, {name}"

print(greet("World"))
"

# mode: 'exec'(模块)、'eval'(表达式)、'single'(单语句)
code_obj = compile(source, '<string>', 'exec')

# 执行编译后的代码
exec(code_obj)  # Hello, World

# eval模式:仅表达式
expr_code = compile('2 + 3 * 4', '<expr>', 'eval')
result = eval(expr_code)
print(result)  # 14
Python
# 编译标志
import ast

#优化级别
code = compile(source, '<string>', 'exec', flags=0)      # 正常
code_opt1 = compile(source, '<string>', 'exec', flags=ast.PyCF_OPTIMIZED_BYTECODE)

# 保留文档字符串(默认会移除)
code = compile(source, '<string>', 'exec', dont_inherit=True)

dis 模块分析字节码

Python
import dis

def simple_add(a, b):
    return a + b

# 反汇编
dis.dis(simple_add)
#  2           0 LOAD_FAST                0 (a)
#              2 LOAD_FAST                1 (b)
#              4 BINARY_ADD
#              6 RETURN_VALUE

# 详细信息
dis.show_code(simple_add)
Python
# 分析控制流
def conditional(x):
    if x > 0:
        return x
    return -x

dis.dis(conditional)
# 对比跳跃指令:POP_JUMP_IF_FALSE
Python
# 字节码操作
code = simple_add.__code__
print(f"字节码长度: {len(code.co_code)}")
print(f"字节码内容: {code.co_code}")  # b'\x7c\x00\x00\x7c\x01\x00\x17\x53\x00'

Code Object 嵌套

Python
def outer():
    def inner():
        return "nested"

    return inner

outer_code = outer.__code__
print(f"外层常量: {outer_code.co_consts}")
# 包含 inner 函数的 Code Object

inner_code = outer_code.co_consts[1]  # 或 outer().__code__
print(f"内层名称: {inner_code.co_name}")  # 'inner'
Python
# 类定义的 Code Object
class MyClass:
    attr = 123

    def method(self):
        return self.attr

# 类体执行后创建类对象
class_code = MyClass.__dict__['__init__'].__code__  # 如果有 __init__

# 查看类定义的字节码
import dis
dis.dis(MyClass)

手动创建 Code Object

Python
import types

# 创建简单的 Code Object(高级用法)
def make_simple_code():
    "创建返回常量的 Code Object"
    return types.CodeType(
        co_argcount=0,
        co_posonlyargcount=0,
        co_kwonlyargcount=0,
        co_nlocals=0,
        co_stacksize=1,
        co_flags=0,
        codetype=b'\x64\x00\x00\x53',  # LOAD_CONST 0; RETURN_VALUE
        co_consts=(42,),
        co_names=(),
        co_varnames=(),
        co_filename='<generated>',
        co_name='generated',
        co_firstlineno=1,
        co_lnotab=b'',
        co_freevars=(),
        co_cellvars=(),
    )

# Python 3.8+ 参数顺序有变化,使用 CodeType.replace 更安全
original_code = simple_add.__code__
new_code = original_code.replace(co_consts=(100, 200))

函数对象重建

Python
import types

def template(a, b):
    "模板函数"
    pass

# 获取模板的 Code Object
template_code = template.__code__

# 创建新函数
new_func = types.FunctionType(
    code=template_code,
    globals=globals(),
    name='new_func',
    argdefs=None,         # 默认参数元组
    closure=None,         # 闭包单元元组
)

# 执行
print(new_func(1, 2))  # 取决于字节码内容

字节码优化分析

Python
import dis

# 常量折叠
def folded():
    return 2 * 3 + 4 * 5

dis.dis(folded)
# 编译时已计算为 26:LOAD_CONST 26

# 循环优化
def loop_unroll():
    result = 0
    for i in range(5):
        result += i
    return result

dis.dis(loop_unroll)
# 查看循环的字节码:SETUP_LOOP, FOR_ITER, STORE_FAST 等

要点总结

  1. Code Object存储字节码、常量、变量名、行号等信息
  2. **compile()**将源码编译为Code Object,支持exec/eval/single模式
  3. dis模块是分析和理解字节码的主要工具
  4. 嵌套函数的Code Object存储在外层函数的co_consts
  5. **types.FunctionType**可用Code Object重建函数对象

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python type元类基础
下一篇 → Python动态类创建
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库