timeit是Python标准库内置的小工具,可以快速测试小段代码的性能。

认识timeit

timeit 函数:

timeit.timeit(stmt, setup,timer, number)

参数说明:

  • stmt: statement的缩写,你要测试的代码或者语句,纯文本,默认值是 "pass"
  • setup: 在运行stmt前的配置语句,纯文本,默认值也是 "pass"
  • timer: 计时器,一般忽略这个参数
  • number: stmt执行的次数,默认是1000000,一百万

repeat 函数:

timeit.repeat(stmt, setup, timer, repeat, number)

是timeit的repeat版,可以指定重复timeit的次数,默认是3次,然后返回一个数组。

举一个简单的例子来说明用法:

import timeit
print(timeit.timeit('output = 10*5')) # 0.014560436829924583
print(timeit.repeat('output = 10*5')) # [0.01492984383367002, 0.01342877489514649, 0.013638464966788888]

嗯,看上去没毛病,实际上谁也不会去测没有意义的加减乘除,我们需要测试自己的代码。

测试多行代码

测试多行代码可以用分号来连接语句。

print(timeit.timeit(stmt='a=10;b=10;sum=a+b'))

也可以用三引号来写stmt。

import timeit
import_module = "import random"
testcode = '''
def test():
return random.randint(10, 100)
'''
print(timeit.repeat(stmt=testcode, setup=import_module))

但是其实都挺扯的,自己的代码会那么简单?我们是模块化编程。

测试模块中的函数

如果你要测试的函数都在一个模块里,可以这样写timeit。

import timeit
import random
import arrow # 本地函数
def stupid1():
return random.randint(1, 10) # 依赖其他函数
def stupid2():
return stupid1() # 依赖其他包或者模块
def stupid3():
return arrow.now() print(timeit.timeit('stupid1()', setup='from __main__ import stupid1'))
print(timeit.timeit('stupid2()', setup='from __main__ import stupid2'))
print(timeit.timeit('stupid3()', setup='from __main__ import stupid3', number=100))

写成上面这样的其实还是单行的模式。

借用default_timer

timeit自带的default_timer可以借来用一下。

import timeit
import random def test():
return random.randint(10, 100) starttime = timeit.default_timer()
print("The start time is :",starttime)
test()
print("The time difference is :", timeit.default_timer() - starttime)

命令行的用法

timeit还支持命令行的调用方式,不过我觉得太累了,没必要去尝试。

C:\pythontest>python -m timeit -s 'text="hello world"'
20000000 loops, best of 5: 13.1 nsec per loop

分享一个案例

2月29那天,我想今年是闰年啊,计算闰年有几种算法啊?孔乙己说有3种:

def is_leap_year_0(year):
if year % 4 == 0:
if year % 100 == 0:
if year % 400 == 0:
return True
else:
return False
else:
return True
else:
return False def is_leap_year_1(year):
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) def is_leap_year_2(year):
if year % 400 == 0:
return True
if year % 100 == 0:
return False
if year % 4 == 0:
return True
return False

这三种方法那种最好啊?这个不能一概而论吧,因为要看你的参数是什么,比如1991年不是闰年,方法0和方法1直接就返回了,但方法2还需要走到最后一个if才知道不是闰年。再比如2020年,方法2直接就返回了,但是方法0和1需要走到最里层的if才得到结果。所以我们需要取样测试才公平,比如从1900年到2900年,每个函数都跑10000遍。

timeit就不太方便了,它接受的参数哪能那么复杂,我们需要包装一下。

def perf_test(method):
years = range(1900, 2900)
if method == 0:
for y in years:
is_leap_year_0(y) if method == 1:
for y in years:
is_leap_year_1(y) if method == 2:
for y in years:
is_leap_year_2(y) print(timeit('perf_test(0)', setup='from __main__ import perf_test', number=10000))
print(timeit('perf_test(1)', setup='from __main__ import perf_test', number=10000))
print(timeit('perf_test(2)', setup='from __main__ import perf_test', number=10000))

你们猜猜看哪个方法结果最好?你一定想不到。

1.6432780250906944
1.7527272370643914
0.0023122059646993876

其他的思路

timeit其实还是太弱了,随便测测还凑合,如果真要检查性能问题还是需要用更专业的手段。比如:

有机会我们下次再说。

关于作者:

Toby Qin, Python 技术爱好者,目前从事测试开发相关工作,转载请注明原文出处。

欢迎关注我的博客 https://betacat.online,你可以到我的公众号中去当吃瓜群众。

使用timeit测试Python函数的性能的更多相关文章

  1. Python内置类型性能分析

    Python内置类型性能分析 timeit模块 timeit模块可以用来测试一小段Python代码的执行速度. class timeit.Timer(stmt='pass', setup='pass' ...

  2. 常用排序算法的python实现和性能分析

    常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...

  3. 【Python】常用排序算法的python实现和性能分析

    作者:waterxi 原文链接 背景 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整 ...

  4. 面试中常用排序算法的python实现和性能分析

    这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...

  5. Python入门笔记(18):Python函数(1):基础部分

    一.什么是函数.方法.过程 推荐阅读:http://www.cnblogs.com/snandy/archive/2011/08/29/2153871.html 一般程序设计语言包含两种基本的抽象:过 ...

  6. 测试c语言函数调用性能因素之测试三

    函数调用:即调用函数调用被调用函数,调用函数压栈,被调用函数执行,调用函数出栈,调用函数继续执行的一个看似简单的过程,系统底层却做了大量操作. 操作: 1,               调用函数帧指针 ...

  7. 用C语言模仿Python函数

    首先得说明一点,C 语言不是函数式编程语言,要想进行完全的函数式编程,还得先写个虚拟机,然后再写个解释器才行(相当于 CPython ). 下面我们提供一个例子,说明 C 语言函数可以"适度 ...

  8. Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

    由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二 ...

  9. python函数,模块及eclipse使用

    一.eclipse的使用 1.作用 (1)最好用的IDE (2)可调式debug (3)查看可执行过程 (4)可查看源代码 2.安装eclipse及配置 目录安装Pythonpython for ec ...

随机推荐

  1. 二、linux-mysql -cmake方式安装mysql 5.5

    1.安装解压cmake包  cmake软件cd /home/oldboy/tools/tar xf cmake-2.8.8.tar.gzcd cmake-2.8.8./configure#CMake ...

  2. rework-发出你的心声

    生意人虚张声势的时候会给人什么感觉?都是些僵硬的措辞.官方的腔调.虚伪的友善.法律术语等.你一定看过这些玩意儿,就好像是机器人写出来的东西,这些公司在向你发话,而不是和你对话. 这种专业主义面具让人觉 ...

  3. OA项目-xadmin使用

    ###############  xadmin安装和配置   ############### """ 环境: Python3.6.3 django1.11.11 创建dj ...

  4. Mysql 和 Java对比异同

    1.求两个时间的差(天数) mysql : to_days 距离公元0年的天数 select TO_DAYS('2017-10-18 00:00:00'),TO_DAYS(NOW()), (TO_DA ...

  5. [LC] 107. Binary Tree Level Order Traversal II

    Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...

  6. C++ 中类的内存布局

    在许多笔试面试中都会涉及到sizeof 运算符的求值问题. 这类问题主要分四类: 基本数据类型,如int,bool,fload,long,long,int * 等,这一类比较简单,但要注意x86和x6 ...

  7. Gas Station(Medium)

    1.在做pat的to fill or not to fill的时候想起同样是加油站的题目,于是翻出来复习一下 2.关键在于理解潜在的条件.假设油量为tank,如果到了当前站i,tank<0,即不 ...

  8. .vimrc文件

    1 set number 2 set shiftwidth=4 3 set softtabstop=4 4 set tabstop=4 5 set expandtab 6 "set hlse ...

  9. Linux考试试题

    mkdir -p /data/oldboy touch lodboy.txt echo "inet addr:10.0.0.8  Bcast:10.0.0.255 Mask:255.255. ...

  10. C++逆序输出字符串

    使用库函数 //使用库函数 #include <iostream> #include <string> #include <algorithm> using nam ...