为何对对象属性中的整数求和比直接对整数求和耗时更长?
Python中整数列表与对象列表遍历求和的性能差异
我之前在学校学过Java,现在正在学习Python,发现两类列表的遍历求和速度存在明显差异:一类存储单个整数,另一类存储带有多个属性的对象。我原本以为对象只是内存指针,性能差距不会太大,但实际测试下来并非如此。
基础测试示例
int_list = [1] * 1000 obj_list = [CustObject(0,1,2,3)] * 1000 total = 0 for i in int_list: total += i print(total) total = 0 for o in obj_list: total += o.int_variable print(total)
复杂Tile对象测试
我用包含约20个属性(其中一个是图像)的Tile对象做了进一步测试,不仅Tile列表的创建耗时更久(符合预期),遍历求和的速度也慢了将近一倍。测试代码如下:
import time print("starting test") ints = [[1 for i in range(100)] for j in range(80)] print("created ints") tiles = [[Tile(i, j, 30, 1) for i in range(100)] for j in range(80)] print("created tiles") # 遍历整数列表求和 start_time = time.perf_counter() total = 0 for i in range(0, len(ints)): for j in range(0, len(ints[i])): total += ints[i][j] end_time = time.perf_counter() elapsed_time = end_time - start_time print("Ints Elapsed time: ", elapsed_time, total) # 遍历Tile对象列表求和 start_time = time.perf_counter() total = 0 for i in range(0, len(tiles)): for j in range(0, len(tiles[i])): total += tiles[i][j].tile_type end_time = time.perf_counter() elapsed_time = end_time - start_time print("Tiles Elapsed time: ", elapsed_time, total)
测试输出
starting test created ints created tiles Ints Elapsed time: 0.0011542000574991107 8000 Tiles Elapsed time: 0.002249700017273426 8000
性能差异原因
属性访问的额外开销:Python中对象确实以内存指针形式存储,但访问对象属性时,需要在对象的属性字典(或类的属性槽)中查找对应名称,这个查找过程比直接读取整数多了额外步骤。而整数列表的元素可直接加载到CPU寄存器运算,无额外查找开销。
内存布局与缓存效率:整数列表在内存中存储更连续(小整数还有全局缓存优化),CPU缓存命中率高;而对象列表存储的是指向分散内存地址的指针,尤其是包含图像这类大属性的Tile对象,内存分布更零散,容易触发缓存失效,拖慢遍历速度。
动态语言特性开销:Python作为动态语言,属性访问时会进行类型检查、可能触发描述器逻辑(如
__getattribute__),这些运行时额外操作都是整数读取不需要的。
优化建议
- 提前提取属性到单独列表:如果频繁需要计算对象某一属性的值,可先把该属性提取为整数列表,后续直接遍历这个列表:
tile_type_list = [[t.tile_type for t in row] for row in tiles] # 后续遍历tile_type_list求和,性能接近整数列表 - 使用slots优化对象:用
@dataclasses.dataclass(slots=True)或attrs库定义对象,slots可以避免属性字典的开销,提升属性访问速度。 - 用内置函数替代手动循环:内置函数由C实现,比纯Python循环高效很多,比如用
sum()结合生成器:# 整数列表求和 total = sum(sum(row) for row in ints) # Tile属性求和 total = sum(t.tile_type for row in tiles for t in row)
内容的提问来源于stack exchange,提问作者digitalfoss
相关产品推荐
相关产品推荐

