今天我們來運用前幾天所學,寫一個計算函式執行時間的函式。
我們希望這個函式可以計算各種奇形怪狀的函式,當然也要能吃下各種引數。
我們的函式 time_it 會有以下的參數:
import time
def time_it(fn, *args, rep=5, **kwargs):
print(args, rep, kwargs)
預設我們會跑被計算的 function 五次:
time_it(print, 1, 2, 3, sep='-')
(1, 2, 3) 5 {'sep': '-'}
修改一下:
def time_it(fn, *args, rep=5, **kwargs):
for i in range(rep):
fn(*args, **kwargs)
time_it(print, 1, 2, 3, sep='-')
1-2-3
1-2-3
1-2-3
1-2-3
1-2-3
成功把 print 執行五次了,而且 sep 參數用到 '-'。
還可以再加更多引數:
time_it(print, 1, 2, 3, sep='-', end=' *** ', rep=3)
1-2-3 *** 1-2-3 *** 1-2-3 ***
再修改一下,要真正開始計算時間了:
def time_it(fn, *args, rep=5, **kwargs):
start = time.perf_counter()
for i in range(rep):
fn(*args, **kwargs)
end = time.perf_counter()
return (end - start) / rep
OK,現在來寫幾個準備被計算執行時間的函式:
我們寫個函式,列出整數 n 從 start 次方到 end 次方:
def compute_powers_1(n, *, start=1, end):
# 使用 loop 的版本
results = []
for i in range(start, end):
results.append(n**i)
return results
def compute_powers_2(n, *, start=1, end):
# 使用串列生成式的版本
return [n**i for i in range(start, end)]
def compute_powers_3(n, *, start=1, end):
# 使用 generator 的版本
return (n**i for i in range(start, end))
來跑跑看:
compute_powers_1(2, end=5)
[2, 4, 8, 16]
compute_powers_2(2, end=5)
[2, 4, 8, 16]
list(compute_powers_3(2, end=5))
[2, 4, 8, 16]
最後用一開始寫的 time_it 來計算一下時間:
time_it(compute_powers_1, n=2, end=20000, rep=4)
0.3699034999990545
time_it(compute_powers_2, 2, end=20000, rep=4)
0.3647651249993942
time_it(compute_powers_3, 2, end=20000, rep=4)
6.980008038226515e-07
可以看到產生一個 generator 比產生一個陣列快很多。
今年的鐵人賽到此,我們明年見~
參考:Python 3: Deep Dive (Part 1 - Functional)