字节码优化:如何通过理解字节码写出更快代码
请以具体代码示例说明,理解Python字节码指令如何帮助写出更高效的代码。对比局部变量vs全局变量访问、属性访问缓存、列表推导式vs for循环、f-string vs format的字节码差异。
回答
古法程序员
1. 局部变量 vs 全局变量
def local_access():
s = 0
for i in range(1000):
s += i
return s
def global_access():
for i in range(1000):
global s
s += i
return s
字节码差异: local_access使用LOAD_FAST(索引访问),global_access使用LOAD_GLOBAL(字典查找)。LOAD_FAST快约2-3倍。
优化技巧: 将频繁访问的全局函数赋给局部变量:
# 慢
for i in range(1000):
print(i)
# 快
_print = print
for i in range(1000):
_print(i)
2. 属性访问缓存
# 慢 — 每次循环执行属性查找
for item in items:
process(item.name, item.value)
# 快 — 缓存方法
name_attr = item.name # LOAD_ATTR
value_attr = item.value
for item in items:
process(name_attr, value_attr)
3. 列表推导式 vs for循环
# for循环 — 多次LOAD_FAST/STORE_FAST + LIST_APPEND
result = []
for x in range(100):
result.append(x * 2)
# 列表推导式 — 单个LIST_COMP(特殊字节码,更快)
result = [x * 2 for x in range(100)]
列表推导式使用LIST_COMP/SET_COMP/DICT_COMP字节码,比手写循环快约30-50%。
4. f-string vs format
# str.format — 调用函数,运行时解析格式字符串
f'Value: {x}'.format(x=42)
# f-string — 编译为FORMAT_VALUE字节码
f'Value: {42}'
f-string在编译期解析,生成FORMAT_VALUE指令,无需函数调用开销。
核心原则: 减少LOAD_GLOBAL/LOAD_ATTR,多用LOAD_FAST和列表推导式等编译器特化指令。