You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何对对象属性中的整数求和比直接对整数求和耗时更长?

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

性能差异原因

  1. 属性访问的额外开销:Python中对象确实以内存指针形式存储,但访问对象属性时,需要在对象的属性字典(或类的属性槽)中查找对应名称,这个查找过程比直接读取整数多了额外步骤。而整数列表的元素可直接加载到CPU寄存器运算,无额外查找开销。

  2. 内存布局与缓存效率:整数列表在内存中存储更连续(小整数还有全局缓存优化),CPU缓存命中率高;而对象列表存储的是指向分散内存地址的指针,尤其是包含图像这类大属性的Tile对象,内存分布更零散,容易触发缓存失效,拖慢遍历速度。

  3. 动态语言特性开销: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:33:17