自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

手把手教你實(shí)現(xiàn)一個(gè) Python 計(jì)時(shí)器

開發(fā) 前端
雖然許多數(shù)據(jù)工作者認(rèn)為 Python 是一種有效的編程語言,但純 Python 程序比C、Rust 和 Java 等編譯語言中的對(duì)應(yīng)程序運(yùn)行得更慢,為了更好地監(jiān)控和優(yōu)化Python程序,云朵君將和大家一起學(xué)習(xí)如何使用 Python 計(jì)時(shí)器來監(jiān)控程序運(yùn)行的速度,以便正對(duì)性改善代碼性能。

為了更好地掌握 Python 計(jì)時(shí)器的應(yīng)用,我們后面還補(bǔ)充了有關(guān)Python類、上下文管理器和裝飾器的背景知識(shí)。因篇幅限制,其中利用上下文管理器和裝飾器優(yōu)化 Python 計(jì)時(shí)器,將在后續(xù)文章學(xué)習(xí),不在本篇文章范圍內(nèi)。

Python 計(jì)時(shí)器

首先,?我們向某段代碼中添加一個(gè)Python 計(jì)時(shí)器以監(jiān)控其性能。

Python 定時(shí)器函數(shù)

Python 中的內(nèi)置time[1]模塊中有幾個(gè)可以測量時(shí)間的函數(shù):

  • monotonic()
  • perf_counter()
  • process_time()
  • time()

Python 3.7 引入了幾個(gè)新函數(shù),如thread_time()[2],以及上述所有函數(shù)的納秒版本,以_ns?后綴命名。例如,perf_counter_ns()?是perf_counter()的納秒版本的。

perf_counter()

返回性能計(jì)數(shù)器的值(以秒為單位),即具有最高可用分辨率的時(shí)鐘以測量短持續(xù)時(shí)間。

首先,使用perf_counter()?創(chuàng)建一個(gè) Python 計(jì)時(shí)器。將把它與其他 Python 計(jì)時(shí)器函數(shù)進(jìn)行比較,看看 perf_counter() 的優(yōu)勢。

示例

創(chuàng)建一個(gè)腳本,?定義一個(gè)簡短的函數(shù):從清華云?上下載一組數(shù)據(jù)。

import requests
def main():
source_url = 'https://cloud.tsinghua.edu.cn/d/e1ccfff39ad541908bae/files/?p=%2Fall_six_datasets.zip&dl=1'
headers = {'User-Agent': 'Mozilla/5.0'}
res = requests.get(source_url, headers=headers)
with open('dataset/datasets.zip', 'wb') as f:
f.write(res.content)

if __name__=="__main__":
main()

我們可以使用 Python 計(jì)時(shí)器來監(jiān)控該?腳本的性能。

第一個(gè) Python 計(jì)時(shí)器

現(xiàn)在使用函數(shù)time.perf_counter()?函數(shù)創(chuàng)建一個(gè)計(jì)時(shí)器,這是一個(gè)非常適合針對(duì)部分代碼的性能計(jì)時(shí)的計(jì)數(shù)器。

perf_counter()?從某個(gè)未指定的時(shí)刻開始測量時(shí)間(以秒為單位),這意味著對(duì)該函數(shù)的單個(gè)調(diào)用的返回值沒有用。但當(dāng)查看對(duì)perf_counter()兩次調(diào)用之間的差異時(shí),可以計(jì)算出兩次調(diào)用之間經(jīng)過了多少秒。

>>> import time
>>> time.perf_counter()
394.540232282

>>> time.perf_counter() # 幾秒鐘后
413.31714087

在此示例中,兩次調(diào)用 perf_counter() 相隔近 19 秒??梢酝ㄟ^計(jì)算兩個(gè)輸出之間的差異來確認(rèn)這一點(diǎn):413.31714087 - 394.540232282 = 18.78。

現(xiàn)在可以將 Python 計(jì)時(shí)器添加到示例代碼中:

# download_data.py
import requests
import time
def main():
tic = time.perf_counter()
source_url = 'https://cloud.tsinghua.edu.cn/d/e1ccfff39ad541908bae/files/?p=%2Fall_six_datasets.zip&dl=1'
headers = {'User-Agent': 'Mozilla/5.0'}
res = requests.get(source_url, headers=headers)
with open('dataset/datasets.zip', 'wb') as f:
f.write(res.content)
toc = time.perf_counter()
print(f"該程序耗時(shí): {toc - tic:0.4f} seconds")
if __name__=="__main__":
main()

注意perf_counter()?通過計(jì)算兩次調(diào)用之間的差異來打印整個(gè)程序運(yùn)行所花費(fèi)的時(shí)間。

print()?函數(shù)中 f? 字符串前面的表示這是一個(gè) f-string? ,這是格式化文本字符串的較為便捷的?方式。:0.4f?是一個(gè)格式說明符,表示數(shù)字,toc - tic應(yīng)打印為帶有四位小數(shù)的十進(jìn)制數(shù)。

運(yùn)行程序可以看到程序經(jīng)過的時(shí)間:

該程序耗時(shí): 0.026 seconds

就是這么簡單。接下來我們一起學(xué)習(xí)如何將 Python 計(jì)時(shí)器包裝到一個(gè)類、一個(gè)上下文管理器和一個(gè)裝飾器中(該系列后續(xù)兩篇文章,待更新)?,這樣可以更加一致和方便使用計(jì)時(shí)器。

一個(gè) Python 定時(shí)器類

這里我們至少需要一個(gè)變量?來存儲(chǔ) Python 計(jì)時(shí)器的狀態(tài)。接下來?我們創(chuàng)建一個(gè)與手動(dòng)調(diào)用 perf_counter() 相同的類,但更具可讀性和一致性?。

創(chuàng)建和更新Timer類,?使用該類以多種不同方式對(duì)代碼進(jìn)行計(jì)時(shí)。

$ python -m pip install codetiming

理解 Python 中的類?

Class?類是面向?qū)ο缶幊痰闹饕獦?gòu)建塊。類本質(zhì)上是一個(gè)模板,可以使用它來創(chuàng)建對(duì)象。

在 Python 中,當(dāng)需要對(duì)需要跟蹤特定狀態(tài)的事物進(jìn)行建模時(shí),類非常有用。一般來說,類是屬性的集合,稱為屬性,以及行為,稱為方法。

創(chuàng)建 Python 計(jì)時(shí)器類

類有利于跟蹤狀態(tài)。在Timer?類中,想要跟蹤計(jì)時(shí)器何時(shí)開始以及已經(jīng)多少時(shí)間。對(duì)于Timer?類的第一個(gè)實(shí)現(xiàn),將添加一個(gè)._start_time?屬性以及.start()?和.stop()?方法。將以下代碼添加到名為 timer.py 的文件中:

# timer.py
import time
class TimerError(Exception):
"""一個(gè)自定義異常,用于報(bào)告使用Timer類時(shí)的錯(cuò)誤"""

class Timer:
def __init__(self):
self._start_time = None

def start(self):
"""Start a new timer"""
if self._start_time is not None:
raise TimerError(f"Timer is running. Use .stop() to stop it")
self._start_time = time.perf_counter()

def stop(self):
"""Stop the timer, and report the elapsed time"""
if self._start_time is None:
raise TimerError(f"Timer is not running. Use .start() to start it")

elapsed_time = time.perf_counter() - self._start_time
self._start_time = None
print(f"Elapsed time: {elapsed_time:0.4f} seconds")

這里我們需要花點(diǎn)時(shí)間仔細(xì)地瀏覽代碼,會(huì)發(fā)現(xiàn)一些不同的事情。

首先定義了一個(gè)TimerError? Python 類。該(Exception)?符號(hào)表示TimerError? 繼承自另一個(gè)名為Exception?的父類。使用這個(gè)內(nèi)置類進(jìn)行錯(cuò)誤處理。不需要向TimerError?添加任何屬性或方法,但自定義錯(cuò)誤可以更靈活地處理Timer內(nèi)部問題。

接下來自定義Timer?類。當(dāng)從一個(gè)類創(chuàng)建或?qū)嵗粋€(gè)對(duì)象時(shí),代碼會(huì)調(diào)用特殊方法.__init__()?初始化實(shí)例。在這里定義的第一個(gè)Timer?版本中,只需初始化._start_time?屬性,將用它來跟蹤 Python 計(jì)時(shí)器的狀態(tài),計(jì)時(shí)器未運(yùn)行時(shí)它的值為None。計(jì)時(shí)器運(yùn)行后,用它來跟蹤計(jì)時(shí)器的啟動(dòng)時(shí)間。

注意: ._start_time?的第一個(gè)下劃線(_)?前綴是Python約定。它表示._start_time是Timer類的用戶不應(yīng)該操作的內(nèi)部屬性。

當(dāng)調(diào)用.start()?啟動(dòng)新的 Python 計(jì)時(shí)器時(shí),首先檢查計(jì)時(shí)器是否運(yùn)行。然后將perf_counter()?的當(dāng)前值存儲(chǔ)在._start_time中。

另一方面,當(dāng)調(diào)用.stop()?時(shí),首先檢查Python計(jì)時(shí)器是否正在運(yùn)行。如果是,則將運(yùn)行時(shí)間計(jì)算為perf_counter()?的當(dāng)前值與存儲(chǔ)在._start_time?中的值的差值。最后,重置._start_time,以便重新啟動(dòng)計(jì)時(shí)器,并打印運(yùn)行時(shí)間。

以下是使用Timer方法:

from timer import Timer
t = Timer()
t.start()
# 幾秒鐘后
t.stop()
Elapsed time: 3.8191 seconds

將此示例與前面直接使用perf_counter()的示例進(jìn)行比較。代碼的結(jié)構(gòu)相似,但現(xiàn)在代碼更清晰了,這也是使用類的好處之一。通過仔細(xì)選擇類、方法和屬性名稱,可以使你的代碼非常具有描述性!

使用 Python 計(jì)時(shí)器類

現(xiàn)在Timer?類中寫入download_data.py。只需要對(duì)以前的代碼進(jìn)行一些更改:

# download_data.py
import requests
from timer import Timer
def main():
t = Timer()
t.start()
source_url = 'https://cloud.tsinghua.edu.cn/d/e1ccfff39ad541908bae/files/?p=%2Fall_six_datasets.zip&dl=1'
headers = {'User-Agent': 'Mozilla/5.0'}
res = requests.get(source_url, headers=headers)
with open('dataset/datasets.zip', 'wb') as f:
f.write(res.content)
t.stop()
if __name__=="__main__":
main()

注意,該代碼與之前使用的代碼非常相似。除了使代碼更具可讀性之外,Timer還負(fù)責(zé)將經(jīng)過的時(shí)間打印到控制臺(tái),使得所用時(shí)間的記錄更加一致。運(yùn)行代碼時(shí),得到的輸出幾乎相同:

Elapsed time: 0.502 seconds
...

打印經(jīng)過的時(shí)間Timer可能是一致的,但這種方法好像不是很靈活。下面我們添加一些更加靈活的東西到代碼中。?

增加更多的便利性和靈活性

到目前為止,我們已經(jīng)了解到類適用于我們想要封裝狀態(tài)并確保代碼一致性的情況。在本節(jié)中,我們將一起給 Python 計(jì)時(shí)器加入更多便利性和靈活性,那?怎么做呢?

  • 在報(bào)告消耗的時(shí)間時(shí),使用可調(diào)整的文本和格式
  • 將日志記錄?打印到控制臺(tái)、寫入到?日志文件或程序的其他部分
  • 創(chuàng)建一個(gè)可以在多次調(diào)用中可積累的Python計(jì)時(shí)器
  • 構(gòu)建 Python 計(jì)時(shí)器的信息表示

首先,自定義用于報(bào)告所用時(shí)間的文本。在前面的代碼中,文本 f"Elapsed time: {elapsed_time:0.4f} seconds"? 被生?硬編碼到 .stop() ?中。如若想使得類代碼更加靈活, 可以使用實(shí)例變量,其值通常作為參數(shù)傳遞給.__init__()?并存儲(chǔ)到 self 屬性。為方便起見,我們還可以提供合理的默認(rèn)值。

要添加.text?為Timer?實(shí)例變量,可執(zhí)行以下操作timer.py:

# timer.py
def __init__(self, text="Elapsed time: {:0.4f} seconds"):
self._start_time = None
self.text = text

注意,默認(rèn)文本"Elapsed time: {:0.4f} seconds"?是作為一個(gè)常規(guī)字符串給出的,而不是f-string?。這里不能使用f-string?,因?yàn)閒-string會(huì)立即計(jì)算,當(dāng)你實(shí)例化Timer時(shí),你的代碼還沒有計(jì)算出消耗的時(shí)間。

注意: 如果要使用f-string?來指定.text,則需要使用雙花括號(hào)來轉(zhuǎn)義實(shí)際經(jīng)過時(shí)間將替換的花括號(hào)。

如:f"Finished {task} in {{:0.4f}} seconds"?。如果task?的值是"reading"?,那么這個(gè)f-string?將被計(jì)算為"Finished reading in {:0.4f} seconds"。

在.stop()?中,.text?用作模板并使用.format()方法填充模板:

# timer.py
def stop(self):
"""Stop the timer, and report the elapsed time"""
if self._start_time is None:
raise TimerError(f"Timer is not running. Use .start() to start it")

elapsed_time = time.perf_counter() - self._start_time
self._start_time = None
print(self.text.format(elapsed_time))

在此更新為timer.py之后,可以將文本更改如下:

from timer import Timer
t = Timer(text="You waited {:.1f} seconds")
t.start()
# 幾秒鐘后
t.stop()
You waited 4.1 seconds

接下來,我們不只是想將消息打印到控制臺(tái),還想保存時(shí)間測量結(jié)果,這樣可以便于將它們存儲(chǔ)在數(shù)據(jù)庫中??梢酝ㄟ^從.stop()?返回elapsed_time的值來實(shí)現(xiàn)這一點(diǎn)。然后,調(diào)用代碼可以選擇忽略該返回值或保存它以供以后處理。

如果想要將Timer集成到日志logging中。要支持計(jì)時(shí)器的日志記錄或其他輸出,需要更改對(duì)print()的調(diào)用,以便用戶可以提供自己的日志記錄函數(shù)。這可以用類似于你之前定制的文本來完成:

# timer.py
# ...
class Timer:
def __init__(
self,
text="Elapsed time: {:0.4f} seconds",
logger=print
):
self._start_time = None
self.text = text
self.logger = logger
# 其他方法保持不變
def stop(self):
"""Stop the timer, and report the elapsed time"""
if self._start_time is None:
raise TimerError(f"Timer is not running. Use .start() to start it")
elapsed_time = time.perf_counter() - self._start_time
self._start_time = None
if self.logger:
self.logger(self.text.format(elapsed_time))

return elapsed_time

不是直接使用print()?,而是創(chuàng)建另一個(gè)實(shí)例變量 self.logger?,引用一個(gè)接受字符串作為參數(shù)的函數(shù)。除此之外,還可以對(duì)文件對(duì)象使用logging.info()?或.write()?等函數(shù)。還要注意if中,它允許通過傳遞logger=None來完全關(guān)閉打印。

以下是兩個(gè)示例,展示了新功能的實(shí)際應(yīng)用:

from timer import Timer
import logging
t = Timer(logger=logging.warning)
t.start()
# 幾秒鐘后
t.stop() # A few seconds later
WARNING:root:Elapsed time: 3.1610 seconds  
3.1609658249999484
t = Timer(logger=None)
t.start()
# 幾秒鐘后
value = t.stop()
value
4.710851433001153

接下來第三個(gè)改進(jìn)是積累時(shí)間度量的能力。例如,在循環(huán)中調(diào)用一個(gè)慢速函數(shù)時(shí),希望以命名計(jì)時(shí)器的形式添加更多的功能,并使用一個(gè)字典來跟蹤代碼中的每個(gè)Python計(jì)時(shí)器。

我們擴(kuò)展download_data.py腳本。

# download_data.py
import requests
from timer import Timer
def main():
t = Timer()
t.start()
source_url = 'https://cloud.tsinghua.edu.cn/d/e1ccfff39ad541908bae/files/?p=%2Fall_six_datasets.zip&dl=1'
headers = {'User-Agent': 'Mozilla/5.0'}
for i in range(10):
res = requests.get(source_url, headers=headers)
with open('dataset/datasets.zip', 'wb') as f:
f.write(res.content)
t.stop()
if __name__=="__main__":
main()

這段代碼的一個(gè)微妙問題是,不僅要測量下載數(shù)據(jù)所需的時(shí)間,還要測量 Python 存儲(chǔ)數(shù)據(jù)到磁盤所花費(fèi)的時(shí)間。這可能并重要,有時(shí)候這兩者所花費(fèi)的時(shí)間可以忽略不計(jì)。但還是希望有一種方法可以精確地計(jì)時(shí)沒一個(gè)步驟,將會(huì)更好。

有幾種方法可以在不改變Timer當(dāng)前實(shí)現(xiàn)的情況下解決這個(gè)問題,且只需要幾行代碼即可實(shí)現(xiàn)。

首先,將引入一個(gè)名為.timers的字典作為Timer的類變量,此時(shí)Timer的所有實(shí)例將共享它。通過在任何方法之外定義它來實(shí)現(xiàn)它:

class Timer:
timers = {}

類變量可以直接在類上訪問,也可以通過類的實(shí)例訪問:

>>> from timer import Timer
>>> Timer.timers
{}

>>> t = Timer()
>>> t.timers
{}

>>> Timer.timers is t.timers
True

在這兩種情況下,代碼都返回相同的空類字典。

接下來向 Python 計(jì)時(shí)器添加可選名稱??梢詫⒃撁Q用于兩種不同的目的:

  1. 在代碼中查找經(jīng)過的時(shí)間
  2. 累加同名定時(shí)器

要向Python計(jì)時(shí)器添加名稱,需要對(duì) timer.py? 進(jìn)行更改。首先,Timer 接受 name 參數(shù)。第二,當(dāng)計(jì)時(shí)器停止時(shí),運(yùn)行時(shí)間應(yīng)該添加到 .timers 中:

# timer.py
# ...
class Timer:
timers = {}
def __init__(
self,
name=None,
text="Elapsed time: {:0.4f} seconds",
logger=print,
):
self._start_time = None
self.name = name
self.text = text
self.logger = logger

# 向計(jì)時(shí)器字典中添加新的命名計(jì)時(shí)器
if name:
self.timers.setdefault(name, 0)

# 其他方法保持不變

def stop(self):
"""Stop the timer, and report the elapsed time"""
if self._start_time is None:
raise TimerError(f"Timer is not running. Use .start() to start it")
elapsed_time = time.perf_counter() - self._start_time
self._start_time = None
if self.logger:
self.logger(self.text.format(elapsed_time))
if self.name:
self.timers[self.name] += elapsed_time
return elapsed_time

注意,在向.timers?中添加新的Python計(jì)時(shí)器時(shí),使用了.setdefault()?方法。它只在沒有在字典中定義name的情況下設(shè)置值,如果name已經(jīng)在.timers中使用,那么該值將保持不變,此時(shí)可以積累幾個(gè)計(jì)時(shí)器:

>>> from timer import Timer
>>> t = Timer("accumulate")
>>> t.start()

>>> t.stop() # A few seconds later
Elapsed time: 3.7036 seconds
3.703554293999332

>>> t.start()

>>> t.stop() # A few seconds later
Elapsed time: 2.3449 seconds
2.3448921170001995

>>> Timer.timers
{'accumulate': 6.0484464109995315}

現(xiàn)在可以重新訪問download_data.py并確保僅測量下載數(shù)據(jù)所花費(fèi)的時(shí)間:

# download_data.py
import requests
from timer import Timer
def main():
t = Timer("download", logger=None)
source_url = 'https://cloud.tsinghua.edu.cn/d/e1ccfff39ad541908bae/files/?p=%2Fall_six_datasets.zip&dl=1'
headers = {'User-Agent': 'Mozilla/5.0'}
for i in range(10):
t.start()
res = requests.get(source_url, headers=headers)
t.stop()
with open('dataset/datasets.zip', 'wb') as f:
f.write(res.content)
download_time = Timer.timers["download"]
print(f"Downloaded 10 dataset in {download_time:0.2f} seconds")

if __name__=="__main__":
main()

現(xiàn)在你有了一個(gè)非常簡潔的版本,Timer它一致、靈活、方便且信息豐富!也可以將本節(jié)中所做的許多改進(jìn)應(yīng)用于項(xiàng)目中的其他類型的類。

Timer改進(jìn)

最后一個(gè)改進(jìn)Timer,以交互方式使用它時(shí)使其更具信息性。下面操作是實(shí)例化一個(gè)計(jì)時(shí)器類,并查看其信息:

>>> from timer import Timer
>>> t = Timer()
>>> t
<timer.Timer object at 0x7f0578804320>

最后一行是 Python 表示對(duì)象的默認(rèn)方式。我們從這個(gè)結(jié)果中看到的信息,并不是很明確,我們接下來對(duì)其進(jìn)行改進(jìn)。

這里介紹一個(gè) dataclasses 類,該類僅包含在 Python 3.7 及更高版本中。

pip install dataclasses

可以使用@dataclass裝飾器將 Python 計(jì)時(shí)器轉(zhuǎn)換為數(shù)據(jù)類

# timer.py
import time
from dataclasses import dataclass, field
from typing import Any, ClassVar
# ...
@dataclass
class Timer:
timers: ClassVar = {}
name: Any = None
text: Any = "Elapsed time: {:0.4f} seconds"
logger: Any = print
_start_time: Any = field(default=None, init=False, repr=False)

def __post_init__(self):
"""Initialization: add timer to dict of timers"""
if self.name:
self.timers.setdefault(self.name, 0)

# 其余代碼不變

此代碼替換了之前的 .__init__() ?方法。請(qǐng)注意數(shù)據(jù)類如何使用類似于之前看到的用于定義所有變量的類變量語法的語法。事實(shí)上,.__init__()是根據(jù)類定義中的注釋變量自動(dòng)為數(shù)據(jù)類創(chuàng)建的。

如果需要注釋變量以使用數(shù)據(jù)類。可以使用此注解向代碼添加類型提示。如果不想使用類型提示,那么可以使用 Any 來注釋所有變量。接下來我們很快就會(huì)學(xué)習(xí)如何將實(shí)際類型提示添加到我們的數(shù)據(jù)類中。

以下是有關(guān) Timer 數(shù)據(jù)類的一些注意事項(xiàng):

  • 第 6 行:@dataclass 裝飾器將Timer 定義為數(shù)據(jù)類。
  • 第 8 行:數(shù)據(jù)類需要特殊的 ClassVar 注釋來指定.timers 是一個(gè)類變量。
  • 第 9 到 11 行:.name?、.text? 和.logger 將被定義為 Timer 上的屬性,可以在創(chuàng)建 Timer 實(shí)例時(shí)指定其值。它們都有給定的默認(rèn)值。
  • 第 12 行:回想一下._start_time? 是一個(gè)特殊屬性,用于跟蹤 Python 計(jì)時(shí)器的狀態(tài),但它應(yīng)該對(duì)用戶隱藏。使用dataclasses.field()?, ._start_time? 應(yīng)該從.__init__() 和 Timer 的表示中刪除。
  • 除了設(shè)置實(shí)例屬性之外,可以使用特殊的 .__post_init__()? 方法進(jìn)行初始化。這里使用它將命名的計(jì)時(shí)器添加到 .timers。

新 Timer 數(shù)據(jù)類與之前的常規(guī)類使用功能一樣,但它現(xiàn)在有一個(gè)很好的信息表示:

from timer import Timer
t = Timer()
t
Timer(name=None, 
text='Elapsed time: {:0.4f} seconds',
logger=<built-in function print>)
t.start()
# 幾秒鐘后
t.stop()
Elapsed time: 6.7197 seconds
6.719705373998295

總結(jié)

現(xiàn)在我們有了一個(gè)非常簡潔的 Timer 版本,它一致、靈活、方便且信息豐富!我們還可以將本文中所做的許多改進(jìn)應(yīng)用于項(xiàng)目中的其他類型的類。

現(xiàn)在我們訪問當(dāng)前的完整源代碼Timer。會(huì)注意到在代碼中添加了類型提示以獲取額外的文檔:

# timer.py

from dataclasses import dataclass, field
import time
from typing import Callable, ClassVar, Dict, Optional

class TimerError(Exception):
"""A custom exception used to report errors in use of Timer class"""

@dataclass
class Timer:
timers: ClassVar[Dict[str, float]] = {}
name: Optional[str] = None
text: str = "Elapsed time: {:0.4f} seconds"
logger: Optional[Callable[[str], None]] = print
_start_time: Optional[float] = field(default=None, init=False, repr=False)

def __post_init__(self) -> None:
"""Add timer to dict of timers after initialization"""
if self.name is not None:
self.timers.setdefault(self.name, 0)

def start(self) -> None:
"""Start a new timer"""
if self._start_time is not None:
raise TimerError(f"Timer is running. Use .stop() to stop it")

self._start_time = time.perf_counter()

def stop(self) -> float:
"""Stop the timer, and report the elapsed time"""
if self._start_time is None:
raise TimerError(f"Timer is not running. Use .start() to start it")

# Calculate elapsed time
elapsed_time = time.perf_counter() - self._start_time
self._start_time = None

# Report elapsed time
if self.logger:
self.logger(self.text.format(elapsed_time))
if self.name:
self.timers[self.name] += elapsed_time

return elapsed_time

總結(jié)下: 使用類創(chuàng)建 Python 計(jì)時(shí)器有幾個(gè)好處:

  • 可讀性:仔細(xì)選擇類和方法名稱,你的代碼將更自然地閱讀。
  • 一致性:將屬性和行為封裝到屬性和方法中,你的代碼將更易于使用。
  • 靈活性:使用具有默認(rèn)值而不是硬編碼值的屬性,你的代碼將是可重用的。

這個(gè)類非常靈活,幾乎可以在任何需要監(jiān)控代碼運(yùn)行時(shí)間的情況下使用它。但是,在接下來的部分中,云朵君將和大家一起了解如何使用上下文管理器和裝飾器,這將更方便地對(duì)代碼塊和函數(shù)進(jìn)行計(jì)時(shí)。

責(zé)任編輯:華軒 來源: 數(shù)據(jù)STUDIO
相關(guān)推薦

2022-06-30 16:10:26

Python計(jì)時(shí)器裝飾器

2022-09-22 12:38:46

antd form組件代碼

2022-08-26 08:01:38

DashWebJavaScrip

2021-06-22 10:43:03

Webpack loader plugin

2023-04-26 12:46:43

DockerSpringKubernetes

2020-12-15 08:58:07

Vue編輯器vue-cli

2023-04-17 09:08:27

CSS計(jì)時(shí)器

2021-07-12 09:03:50

Python任務(wù)管理器cmd命令

2019-08-26 09:25:23

RedisJavaLinux

2020-05-09 09:59:52

Python數(shù)據(jù)土星

2020-12-02 12:29:24

Vue無限級(jí)聯(lián)樹形

2021-11-10 11:40:42

數(shù)據(jù)加解密算法

2009-11-09 14:57:37

WCF上傳文件

2011-01-06 10:39:25

.NET程序打包

2016-11-01 09:46:04

2021-07-14 09:00:00

JavaFX開發(fā)應(yīng)用

2011-01-10 14:41:26

2011-05-03 15:59:00

黑盒打印機(jī)

2011-04-21 10:32:44

MySQL雙機(jī)同步

2011-08-29 18:03:47

設(shè)置路由器路由器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)