Numpy 06-Python实验六-1 一维数组性能测试.py

 

import numpy as np
import time
import timeit

def NativeTest ( ) :
    # Python 列表的性能问题
    python_list = list(range(1000000))

    start_time = time.time()
    result = [x * 2 for x in python_list]
    end_time = time.time()

    print(f"Python列表计算时间: {end_time - start_time:.6f}秒")

def NumpyTest ( ) :
    # NumPy 数组的性能优势
    numpy_array = np.arange(1000000)

    start_time = time.time()
    result = numpy_array * 2
    end_time = time.time()

    print(f"NumPy数组计算时间: {end_time - start_time:.6f}秒")

if __name__ == "__main__" :
    accurateTime = timeit.timeit ( NativeTest, number=20 )
    print ( "使用Python列表,精确的运行时间为:", accurateTime/20 )

    accurateTime = timeit.timeit ( NumpyTest, number=20 )
    print ( "使用Numpy数组,精确的运行时间为:", accurateTime/20 )

 

代码逐行详细讲解

这段代码的核心目的:对比原生 Python 列表 和 NumPy 数组 在批量数值运算的性能差异,直观展示 NumPy 向量化运算为什么远快于 Python 循环。

前置知识点:

  • Python 列表:存放对象,遍历是 Python 层面循环(慢)
  • NumPy 数组:连续内存存放同类型数值,运算在 C 底层执行,没有 Python 循环开销(向量化,快)
  • time.time():获取当前系统时间戳,用来手动计时单次函数
  • timeit:Python 内置精准计时工具,会多次运行代码减少系统波动干扰

完整代码拆分

import numpy as np
import time
import timeit
  1. import numpy as np:导入 numpy 数值计算库,简写为 np
  2. import time:导入基础时间模块,用来获取时间戳手动计时
  3. import timeit:高精度计时模块,适合性能基准测试

函数 1:NativeTest () 原生 Python 列表测试

def NativeTest ( ) :
    # Python 列表的性能问题
    python_list = list(range(1000000))
    start_time = time.time()
    result = [x * 2 for x in python_list]
    end_time = time.time()
    print(f"Python列表计算时间: {end_time - start_time:.6f}秒")

逐行解释:

  1. def NativeTest(): 定义测试函数,测试原生 Python 列表
  2. python_list = list(range(1000000)) 创建一个包含 100 万个整数的 Python 列表,元素:0,1,2,...,999999
  3. start_time = time.time() 记录运算开始的时间戳(单位:秒,浮点数)
  4. result = [x * 2 for x in python_list] 列表推导式:遍历列表中每一个元素,每个元素 ×2,生成新列表。

    ⚠️ 重点:这个循环是Python 解释器层面循环。每一次x*2都要做 Python 对象的查找、解包、运算,开销很大。

  5. end_time = time.time() 记录运算结束时间戳
  6. print(...) 打印本次列表推导运算耗时,保留 6 位小数

注意:python_list = list(range(1000000)) 这一行是创建列表,不在start~end计时区间,不计入运算耗时。计时只测[x*2 ...]这一步。


函数 2:NumpyTest () NumPy 数组测试

def NumpyTest ( ) :
    # NumPy 数组的性能优势
    numpy_array = np.arange(1000000)
    start_time = time.time()
    result = numpy_array * 2
    end_time = time.time()
    print(f"NumPy数组计算时间: {end_time - start_time:.6f}秒")
  1. numpy_array = np.arange(1000000) 创建 numpy 数组,同样 0~999999 共 100 万个数字。 和 list 不同:numpy 数组内存连续,全部是相同类型原始数值(int64),不是 Python 对象。
  2. start_time = time.time() 记录开始时间
  3. result = numpy_array * 2 ✅ NumPy 向量化运算 表面看起来一行代码,底层 C 语言并行批量计算,没有 Python 循环。 数组中所有元素一次性乘以 2,不需要逐个在 Python 里遍历,开销极低。
  4. 打印单次 numpy 运算耗时。

同样:数组创建np.arange不在计时范围,只计时乘法运算。


主程序入口

if __name__ == "__main__" :
    accurateTime = timeit.timeit ( NativeTest, number=20 )
    print ( "使用Python列表,精确的运行时间为:", accurateTime/20 )
    accurateTime = timeit.timeit ( NumpyTest, number=20 )
    print ( "使用Numpy数组,精确的运行时间为:", accurateTime/20 )

if __name__ == "__main__":只有直接运行本 py 文件才执行下面代码;被 import 导入时不执行。

timeit.timeit 详解

accurateTime = timeit.timeit(NativeTest, number=20)
  • timeit.timeit(函数名, number=20):重复调用 NativeTest 一共 20 次,返回20 次运行的总耗时(秒)
  • accurateTime / 20:求单次平均耗时,减少单次运行受操作系统后台进程干扰带来的误差,得到更稳定、可信的性能数据。

注意: timeit 在执行NativeTest的时候,每次都会完整执行整个 NativeTest 函数,包括函数内部的:

  • 创建百万列表
  • 列表推导计算
  • print 打印 所以accurateTime/20得到的平均值 =(创建列表 + 乘法计算 + print)的平均总耗时。

运行结果示例(你本地会略有差异)

Python列表计算时间: 0.045210秒
Python列表计算时间: 0.043156秒
......(一共打印20次)
使用Python列表,精确的运行时间为: 0.044021

NumPy数组计算时间: 0.000820秒
NumPy数组计算时间: 0.000791秒
......(一共打印20次)
使用Numpy数组,精确的运行时间为: 0.000815

👉 可以看到:numpy 数组乘法比 python 列表推导快几十倍。

两个计时方式的区别(容易混淆的点)

  1. 函数内部 time.time():单次运行的计时,每次调用函数都会打印一次单次耗时(一共打印 20 次)
  2. 外部timeit:统计 20 轮总耗时,最后算出平均单次耗时,作为最终基准。

小缺陷: 函数内部还包含 print 打印,打印 IO 会轻微占用时间,对性能测试有微小干扰。正式性能测试一般会去掉函数内部 print。

底层原理总结

  1. Python 列表:存的是一个个 Python 对象,循环由 Python 解释器执行,循环本身开销巨大。数据分散在内存各处。
  2. Numpy 数组:一块连续内存保存原生数值,运算交给底层 C 实现,消除 Python 循环开销(向量化编程),大批量数值运算速度优势巨大。

 

posted @ 2026-10-21 08:03  emanlee  阅读(4)  评论(0)    收藏  举报