我想定義一個包含id、status和countdown timer的物件。一旦我實體化了這個物件,倒計時的計時器就應該立即啟動。
下面是我創建一個類的代碼,該類中定義了一個非執行緒版本的倒計時器
。import time
import sys
from threading import Timer
class UserTimer。
def __init__(self, id=None, current_status=None) 。
self.id=id。
self.current_status = current_status
self.timeout()
def timeout(self)。
print("timeout started for"/span>, self.id)
timeout_limit = 150
秒 = 0
while True:
try:
if seconds == timeout_limit:
print("countdown over for"/span>, self.id)
break。
time.sleep(1)
seconds =1
except KeyboardInterrupt, e:
break
下面是如何實體化它的方法
params1 = {'id': "[email protected]", 'current_status': "success"}。
params2 = {'id': "[email protected]", 'current_status': "success"}。
user1 = UserTimer(**params1)
user2 = UserTimer(**params2)
這里的問題是,當這個程式運行時,它將實體化第一個物件(user1),由于函式time.sleep(),它將在實體化第二個物件(user2)之前等待指定的時間
于是我查找并發現 python 執行緒在這種情況下很有幫助,因為執行緒將獨立運行,不會阻礙代碼的進展。
所以我是這樣修改下面的代碼的
class UserTimer。
def __init__(self, id=None, current_status=None) 。
self.id=id。
self.current_status = current_status
def timeout(self)。
print("time over for"/span>, self.id)
t = Timer(150, timeout)
t.start()
params1 = {'id': "[email protected]", 'current_status': "success"}。
params2 = {'id': "[email protected]", 'current_status': "success"}。
user1 = UserTimer(**params1)
user2 = UserTimer(**params2)
現在兩個物件同時被實體化,但問題是一旦給定的持續時間結束,它就會出現以下錯誤
Exception in thread Thread-1:
回溯(最近一次呼叫)。
檔案 "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", 行 801, in __bootstrap_inner
self.run()
檔案 "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 1073, in run
self.function(*self.args, **self.kwargs)
TypeError: timeout()正好需要1個引數(0給定)。
這是因為它看到了關鍵字self,這是它所不期望的。但是我需要self,因為我需要轉儲一些關于用戶物件的資訊。如果我洗掉self,那么它就可以正常運行。
我是否以錯誤的方式在類中定義了執行緒?我想要的是能夠實體化多個物件,這些物件擁有各自的倒計時器。
此外,我還應該能夠通過類似于user1.reset_timer = True
我在這里做錯了什么?
uj5u.com熱心網友回復:
我從你的代碼中得到了一個與你不同的錯誤:
TypeError: timeout() missing 1 required positional argument: 'self'。
線索是提到了self,這是由于:
t = Timer(150, timeout)
t.start()
你在UserTimer的類主體中,這意味著它在類被定義時被執行(并且還沒有創建self實體)。
解決這個問題的一個簡單方法是通過定義一個__call__()方法(并在正確的時間呼叫它)來使類的實體可被呼叫。以下是我的意思:
import time
import sys
from threading import Timer
class UserTimer。
def __init__(self, id=None, current_status=None, interval=5) 。
self.id=id。
self.current_status = current_status
self.interval = interval
def timeout(self)。
print("time over for"/span>, self.id)
def __call__(self):
self.timer_thread = Timer(self.interval, self.timeout)
self.timer_thread.start()
def cancel(self)。
try:
self.timer_thread.cancel()
except AttributeError:
raise RuntimeError("'UserTimer'物件未啟動。")
params1 = dict(id="[email protected]"/span>, current_status="success")
params2 = dict(id="[email protected]"/span>, current_status="success", interval=6)
user1 = UserTimer(**params1)
user1() # 開始計時。
user2 = UserTimer(**params2)
user2() # Start Timer.
我還按照你的要求添加了cancel()方法,并使時間間隔成為一個容易改變的變數,而不是硬編碼到類的主體中。
uj5u.com熱心網友回復:
你應該把Timer的初始化放在__init__()中,以便在你實體化一個物件時啟動它。
class UserTimer(object)。
def __init__(self, id=None, current_status=None) 。
self.id=id。
self.current_status = current_status
self.start_timer() # 當一個物件被實體化時啟動計時器。
def timeout(self)。
print("time over for"/span>, self.id)
def start_timer(self)。
self.t = Timer(5, self.timeout) # 更改為5秒的演示。
# `self.timeout`而不是`timeout`。
self.t.start()
def reset_timer(self)。
self.t.cancel() # 取消舊的定時器。
self.start_timer() # 并啟動一個新的。
params1 = {'id': "[email protected]"/span>, 'current_status': "success"}。
params2 = {'id': "[email protected]", 'current_status': "success"}。
user1 = UserTimer(**params1)
time.sleep(2) # 假設user2在2秒后被實體化。
print('instantiating user2...'/span>)
user2 = UserTimer(**params2)
time.sleep(3) # 在user2實體化后3秒重置user1的計時器。
print('reseting timer of user1...')
user1.reset_timer()
你可以運行該代碼并檢查計時。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/308316.html
標籤:
