13.13 实现一个计时器¶
问题¶
ä½ æƒ³è®°å½•ç¨‹åº�执行多个任务所花费的时间
解决方案¶
time 模�包�很多函数�执行跟时间有关的函数。
尽管如æ¤ï¼Œé€šå¸¸æˆ‘们会在æ¤åŸºç¡€ä¹‹ä¸Šæž„é€ ä¸€ä¸ªæ›´é«˜çº§çš„æŽ¥å�£æ�¥æ¨¡æ‹Ÿä¸€ä¸ªè®¡æ—¶å™¨ã€‚例如:
import time
class Timer:
def __init__(self, func=time.perf_counter):
self.elapsed = 0.0
self._func = func
self._start = None
def start(self):
if self._start is not None:
raise RuntimeError('Already started')
self._start = self._func()
def stop(self):
if self._start is None:
raise RuntimeError('Not started')
end = self._func()
self.elapsed += end - self._start
self._start = None
def reset(self):
self.elapsed = 0.0
@property
def running(self):
return self._start is not None
def __enter__(self):
self.start()
return self
def __exit__(self, *args):
self.stop()
这个类定义了一个å�¯ä»¥è¢«ç”¨æˆ·æ ¹æ�®éœ€è¦�å�¯åЍã€�å�œæ¢å’Œé‡�置的计时器。
它会在 elapsed 属性ä¸è®°å½•整个消耗时间。
下é�¢æ˜¯ä¸€ä¸ªä¾‹å�æ�¥æ¼”ç¤ºæ€Žæ ·ä½¿ç”¨å®ƒï¼š
def countdown(n):
while n > 0:
n -= 1
# Use 1: Explicit start/stop
t = Timer()
t.start()
countdown(1000000)
t.stop()
print(t.elapsed)
# Use 2: As a context manager
with t:
countdown(1000000)
print(t.elapsed)
with Timer() as t2:
countdown(1000000)
print(t2.elapsed)
讨论¶
本节æ��供了一个简å�•而实用的类æ�¥å®žçŽ°æ—¶é—´è®°å½•ä»¥å�Šè€—时计算。 å�Œæ—¶ä¹Ÿæ˜¯å¯¹ä½¿ç”¨withè¯å�¥ä»¥å�Šä¸Šä¸‹æ–‡ç®¡ç�†å™¨å��议的一个很好的演示。
在计时ä¸è¦�考虑一个底层的时间函数问题。一般æ�¥è¯´ï¼Œ
使用 time.time() 或 time.clock() è®¡ç®—çš„æ—¶é—´ç²¾åº¦å› æ“�作系统的ä¸�å�Œä¼šæœ‰æ‰€ä¸�å�Œã€‚
而使用 time.perf_counter() 函数�以确�使用系统上�最精确的计时器。
上述代ç �ä¸ç”± Timer 类记录的时间是钟表时间,并包å�«äº†æ‰€æœ‰ä¼‘çœ æ—¶é—´ã€‚
å¦‚æžœä½ å�ªæƒ³è®¡ç®—该进程所花费的CPU时间,应该使用 time.process_time() æ�¥ä»£æ›¿ï¼š
t = Timer(time.process_time)
with t:
countdown(1000000)
print(t.elapsed)
time.perf_counter() 和 time.process_time() 都会返回�数形�的秒数时间。
实际的时间值没有任何æ„�义,为了得到有æ„�ä¹‰çš„ç»“æžœï¼Œä½ å¾—æ‰§è¡Œä¸¤æ¬¡å‡½æ•°ç„¶å�Žè®¡ç®—它们的差值。
更多关于计时和性能分æž�的例å�请å�‚考14.13å°�节。