天天看點

python 建構裝飾器計算代碼運作耗時

代碼的運作效率和性能優化是開發人員日常開發關注的重點。

一段好的代碼,最普通的标準是能夠實作功能,接下來是優化代碼,保證功能實作的前提下能夠簡潔代碼行數,通用标準是内置子產品>第三方庫>手動撸碼。

内置子產品作為python語言自帶的系統資源,運作效率最快,消耗資源最少,往往一行代碼就能實作各種騷操作,例如;collections子產品的Counter,可以直接調用統計字元串和清單數組中元素的個數。

那麼,如何判斷代碼是否是上乘代碼就是一個比較有意思的問題了。最常用的方法就是計算代碼的運作時間,比較代碼運作效率,時間越短,效率越高,代碼也就越接近最完美。

1.常見的計算時間的方法

1.1 time内置子產品

1.1.1 time.clock()

python 建構裝飾器計算代碼運作耗時

1.1.2 time.time()

python 建構裝飾器計算代碼運作耗時

time.clock() 傳回的是處理器時間,而因為 Unix 中 jiffy 的緣故,是以精度不會太高。clock轉秒,除以1000000。

time.time()包含了其他程式使用CPU的時間,time.clock()隻計算了程式運作CPU的時間。

究竟是使用 time.clock() 精度高,還是使用 time.time() 精度更高,要視乎所在的平台來決定。總概來講,在 Unix 系統中,建議使用 time.time(),在 Windows 系統中,建議使用 time.clock()。

1.2datetime内置子產品

python 建構裝飾器計算代碼運作耗時

相較于time内置子產品,datetime常用來計算目前時間和日期,所謂術業有專攻,在計算代碼耗時上,datetime的性能是最差的。

1.3timeit内置子產品

前面我們提到過,time内置子產品計算有兩種方法,分别是time.time()和time.clock()函數。根據不同的作業系統選用不同的函數來計算代碼耗時。

在windows系統中使用time.time()就不如time.clock(),相反的在linux系統中使用time.clock()就不如time.time()精度高。

我們需要的是一個通用的計算耗時方法,windows和linux中計算精度一樣的方法。timeit子產品就是為解決這個問題而生的。

timeit子產品主要的兩個函數:

1,    timeit(stmt='pass', setup='pass', timer=<defaulttimer>, number=1000000)

       傳回:

            傳回執行stmt這段代碼number遍所用的時間,機關為秒,float型

       參數:

            stmt:要執行的那段代碼

            setup:執行代碼的準備工作,不計入時間,一般是import之類的

            timer:這個在win32下是time.clock(),linux下是time.time(),預設的,不用管

            number:要執行stmt多少遍

2,    repeat(stmt='pass', setup='pass', timer=<defaulttimer>, repeat=3, number=1000000)

       這個函數比timeit函數多了一個repeat參數而已,表示重複執行timeit這個過程多少遍,傳回一個清單,表示執行每遍的時間
           

timeit()函數用來統計單次代碼的耗時,repeat()函數可以統計多次代碼運作的時間清單。

1.3.1timeit()函數

timeit()函數源碼如下:

python 建構裝飾器計算代碼運作耗時

stmt是要執行的代碼,可以是str字元串,也可以是函數名稱。

number是執行代碼的次數,預設值為default_number,數量為1000000。

簡單的使用timeit()函數:

import timeit
import time


def demo():
    print('哈哈哈')

start = timeit.timeit(stmt=demo, number=1)
print(start)
           

需要注意的是必須設定number為1,預設值會執行代碼1000000次。

2.使用裝飾器将計時方法參數化。

2.1 什麼是裝飾器

函數裝飾器用于在源碼中“标記”函數,以某種方式增強函數的行為

裝飾器是可調用的對象,其參數是另一個函數(被裝飾的函數)。 裝飾器可能會處理被裝飾的函數,然後把它傳回,或者将其替換成另一個函數或可調用對象。

嚴格來說,裝飾器隻是文法糖。

裝飾器可以像正常的可調用對象那樣調用,其參數是另一個函數。有時,這樣做更友善,尤其是做元程式設計(在運作時改變程式的行

為)時。

綜上,裝飾器的一大特性是,能把被裝飾的函數替換成其他函數。第二個特性是,裝飾器在加載子產品時立即執行。

通俗來講:裝飾器是能夠在保證原代碼邏輯不變的前提下,給原代碼添加功能,檢測,檢查,計時,統計等等都可以用到裝飾器。

python 建構裝飾器計算代碼運作耗時

2.2 使用裝飾器将計時方法參數化

我們可以将timeit内置子產品計時的方法作為一個裝飾器,需要計算代碼耗時的函數可以直接使用這個裝飾器來傳回代碼耗時,讓代碼更簡潔。

裝飾器實作方法如下:

# 裝飾器
import timeit
def time_keep(func):
    
    def time_ke():
        elapsed_time = timeit.timeit(stmt=func,number=1)
        print(f'代碼耗時:0.0446')
    return time_ke
           

調用裝飾器:

python 建構裝飾器計算代碼運作耗時

python裝飾器的使用以及古往今來可以參考《流暢的python》。書裡對python裝飾器的介紹比較詳細,有興趣的小夥伴可以了解一下。

參考文獻:

《流暢的python》第七章 函數裝飾器和閉包;

https://www.cnblogs.com/itcomputer/articles/4578769.html timeit子產品的介紹。

繼續閱讀