使用 Python Timeit 为您的代码计时

已发表: 2023-01-17

在本教程中,您将学习如何使用 Python 的 timeit 模块中的 timeit 函数。 您将学习如何在 Python 中为简单的表达式和函数计时。

为代码计时可以帮助您估算一段代码的执行时间,还可以识别需要优化的代码部分。

我们将从学习 Python 的timeit函数的语法开始。 然后我们将编写示例以了解如何使用它来为 Python 模块中的代码块和函数计时。 让我们开始。

如何使用 Python timeit 函数

timeit模块是 Python 标准库的一部分,您可以导入它:

 import timeit

使用timeit模块中的timeit函数的语法如下所示:

 timeit.timeit(stmt, setup, number)

这里:

  • stmt是要测量其执行时间的代码段。 您可以将其指定为简单的 Python 字符串或多行字符串,或传入可调用对象的名称。
  • 顾名思义, setup表示只需要运行一次的代码段,通常作为stmt运行的先决条件。 例如,假设您正在计算创建 NumPy 数组的执行时间。 在这种情况下,导入numpysetup代码,实际创建是要计时的语句。
  • 参数number表示stmt运行的次数。 number的默认值为 100 万 (1000000),但您也可以将此参数设置为您选择的任何其他值。

现在我们已经学习了使用timeit()函数的语法,让我们开始编写一些示例。

计时简单的 Python 表达式

计时简单 Python 表达式

在本节中,我们将尝试使用 timeit 测量简单 Python 表达式的执行时间。

启动 Python REPL 并运行以下代码示例。 在这里,我们正在计算 10000 次和 100000 次运行的求幂和底除运算的执行时间。

请注意,我们将要计时的语句作为 Python 字符串传入,并使用分号分隔语句中的不同表达式。

 >>> import timeit >>> timeit.timeit('3**4;3//4',number=10000) 0.0004020999999738706 >>> timeit.timeit('3**4;3//4',number=100000) 0.0013780000000451764

在命令行运行 Python timeit

您还可以在命令行中使用timeit 。 这是 timeit 函数调用的等效命令行:

 $ python-m timeit -n [number] -s [setup] [stmt]
  • python -m timeit表示我们将timeit作为主模块运行。
  • n是一个命令行选项,表示代码应运行的次数。 这相当于timeit()函数调用中的number参数。
  • 您可以使用选项-s来定义设置代码。

在这里,我们使用等效的命令行重写前面的示例:

 $ python -m timeit -n 100000 '3**4;3//4' 100000 loops, best of 5: 35.8 nsec per loop

在此示例中,我们计算内置len()函数的执行时间。 字符串的初始化是使用s选项传入的设置代码。

 $ python -m timeit -n 100000 -s "string_1 = 'coding'" 'len(string_1)' 100000 loops, best of 5: 239 nsec per loop

在输出中,请注意我们获得了5 次运行中最好的执行时间。 这是什么意思? 当您在命令行运行timeit时, repeat选项r被设置为默认值 5。这意味着指定numberstmt执行将重复五次,并返回最佳执行次数。

使用timeit的字符串反转方法分析

使用 Python 字符串时,您可能希望反转它们。 字符串反转的两种最常见的方法如下:

  • 使用字符串切片
  • 使用reversed()函数和join()方法
使用 timeit 的字符串反转方法分析

使用字符串切片反转 Python 字符串

让我们回顾一下字符串切片的工作原理,以及如何使用它来反转 Python 字符串。 使用语法some-string[start:stop]返回从索引start并向上延伸到索引stop-1的字符串片段。 让我们举个例子。

考虑以下字符串“Python”。 该字符串的长度为 6,索引列表为 0、1、2 到 5。

图片 76
 >>> string_1 = 'Python'

当您同时指定startstop值时,您会得到一个从start延伸到stop-1的字符串切片。 因此, string_1[1:4]返回 'yth'。

图片 77
 >>> string_1 = 'Python' >>> string_1[1:4] 'yth'

当您未指定start时,将使用默认start​​零,切片从索引零开始,一直延伸到stop - 1

图片-78

在这里, stop值为 3,因此切片从索引 0 开始,一直到索引 2。

 >>> string_1[:3] 'Pyt'

当您不包括stop索引时,您会看到切片从start索引 (1) 开始并一直延伸到字符串的末尾。

图片80
 >>> string_1[1:] 'ython'

忽略start值和stop值将返回整个字符串的一部分。

图片81
 >>> string_1[::] 'Python'

让我们用step值创建一个切片。 将startstopstep值分别设置为 1、5 和 2。 我们得到一段字符串,从 1 开始延伸到 4(不包括结束点 5),包含每隔一个字符

图片82
 >>> string_1[1:5:2] 'yh'

当您使用负步时,您可以获得从字符串末尾开始的切片。 将步长设置为 -2, string_1[5:2:-2]给出以下切片:

图片83
 >>> string_1[5:2:-2] 'nh'

因此,为了获得字符串的反向副本,我们跳过startstop值并将步长设置为 -1,如下所示:

 >>> string_1[::-1] 'nohtyP'

总之: string[::-1]返回字符串的反向副本。

使用内置函数和字符串方法反转字符串

Python 中的内置reversed()函数将返回字符串元素的反向迭代器。

 >>> string_1 = 'Python' >>> reversed(string_1) <reversed object at 0x00BEAF70>

因此,您可以使用 for 循环遍历反向迭代器:

 for char in reversed(string_1): print(char)

并以相反的顺序访问字符串的元素。

 # Output n o h t y P

接下来,您可以使用以下语法在反向迭代器上调用join()方法: <sep>.join(reversed(some-string))

下面的代码片段显示了几个示例,其中分隔符分别是连字符和空格。

 >>> '-'.join(reversed(string1)) 'nohtyP' >>> ' '.join(reversed(string1)) 'nohty P'

在这里,我们不需要任何分隔符; 所以将分隔符设置为空字符串以获取字符串的反向副本:

 >>> ''.join(reversed(string1)) 'nohtyP'

使用''.join(reversed(some-string))返回字符串的反向副本。

使用 timeit 比较执行时间

到目前为止,我们已经学习了两种反转 Python 字符串的方法。 但是他们中哪个更快呢? 让我们找出来。

在我们为简单的 Python 表达式计时的先前示例中,我们没有任何setup代码。 在这里,我们正在反转 Python 字符串。 当字符串反转操作运行 number 指定的number时, setup代码是只运行一次的字符串的初始化。

 >>> import timeit >>> timeit.timeit(stmt = 'string_1[::-1]', setup = "string_1 = 'Python'", number = 100000) 0.04951830000001678 >>> timeit.timeit(stmt = "''.join(reversed(string_1))", setup = "string_1 = 'Python'", number = 100000) 0.12858760000000302

对于反转给定字符串的相同运行次数,字符串切片方法比使用join()方法和reversed()函数更快。

使用 timeit 为 Python 函数计时

计时-Python-函数-使用-timeit

在本节中,让我们学习如何使用 timeit 函数为 Python 函数计时。 给定一个字符串列表,以下函数hasDigit返回至少有一个数字的字符串列表。

 def hasDigit(somelist): str_with_digit = [] for string in somelist: check_char = [char.isdigit() for char in string] if any(check_char): str_with_digit.append(string) return str_with_digit

现在我们想使用timeit测量这个 Python 函数hasDigit()的执行时间。

让我们首先确定要计时的语句 ( stmt )。 它是对函数hasDigit()的调用,以字符串列表作为参数。 接下来,让我们定义设置代码。 你能猜出setup代码应该是什么吗?

要成功运行函数调用,设置代码应包括以下内容:

  • 函数hasDigit()的定义
  • 字符串参数列表的初始化

让我们在setup字符串中定义设置代码,如下所示:

 setup = """ def hasDigit(somelist): str_with_digit = [] for string in somelist: check_char = [char.isdigit() for char in string] if any(check_char): str_with_digit.append(string) return str_with_digit thislist=['puffin3','7frost','blue'] """

接下来,我们可以使用timeit函数并获取hasDigit()函数运行 100000 次的执行时间。

 import timeit timeit.timeit('hasDigit(thislist)',setup=setup,number=100000)
 # Output 0.2810094920000097

结论

您已经学习了如何使用Python 的 timeit 函数为表达式、函数和其他可调用对象计时。 这可以帮助您对代码进行基准测试,比较同一函数的不同实现的执行时间,等等。

让我们回顾一下我们在本教程中学到的内容。 您可以使用语法timeit.timeit(stmt=...,setup=...,number=...)timeit()函数。 或者,您可以在命令行运行 timeit 来为短代码片段计时。

下一步,您可以探索如何使用其他 Python 分析包(如 line-profiler 和 memprofiler)分别针对时间和内存分析您的代码。

接下来,学习如何在 Python 中计算时差。