使用 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 中計算時差。