目錄:
一、簡單定製
二、課時44課後習題及答案
****************
一、簡單定製
****************
基本要求:
1>> 定製一個計時器的類
2>> start和stop方法代表啟動計時和停止計時
3>> 假設計時器物件t1,print(t1)和直接呼叫t1均顯示結果
4>> 當計時器未啟動或已經停止計時,呼叫stop方法會給予溫馨的提示
5>> 兩個計時器物件可以進行相加:t1 + t2
6>> 只能使用提供的有限資源完成
你需要這些資源:
1>> 使用time模組的localtime方法獲取時間
【擴充套件閱讀】:time 模組詳解(時間獲取和轉換)
2>> time.localtime返回struct_time的時間格式
3>> 表現你的類:__str__ ()和 __repr__()魔法方法
>>> class A: def __str__(self): return "小甲魚是帥哥" >>> a = A() >>> print(a) 小甲魚是帥哥 >>> a <__main__.A object at 0x0000020BB2E537F0> >>> class B: def __repr__(self): return "小甲魚是帥哥" >>> b = B() >>> b 小甲魚是帥哥
有了這些知識,可以開始編寫程式碼了:
import time as t class MyTimer: #開始計時 def start(self): self.start = t.localtime() print("計時開始...") #停止計時 def stop(self): self.stop = t.localtime() print("計時結束!") """ 好,萬丈高樓平地起,把地基寫好後,應該考慮怎麼進行計算了。 localtime()返回的是一個時間元組的結構,只需要在前邊6個元素, 然後將stop的元素依此減去start對應的元素,將差值存放在一個新的列表裡: """ #停止計時 def stop(self): self.stop = t.localtime() self._calc() print("計時結束!") # 內部方法,計算執行時間 def _calc(self): self.lasted = [] self.prompt = "總共執行了" for index in range(6): self.lasted.append(self.stop[index] - self.start[index]) self.prompt += str(self.lasted[index]) print(self.prompt)
>>> t1 = MyTimer() >>> t1.start() 計時開始... >>> t1.stop() 總共執行了000008 計時結束!
已經基本實現計時功能了,接下來需要完成“print(t1)和直接呼叫t1均顯示結果”,那就要通過重寫__str__()和__repr__()魔法方法來實現:
def __str__(self): return self.prompt __repr__ = __str__
>>> t1 = MyTimer() >>> t1.start() 計時開始... >>> t1.stop() 總共執行了000004 計時結束! >>> t1 總共執行了000004
似乎做得很不錯了,但這裡還有一些問題。假使使用者不按常理出牌,問題就會很多:
>>> t1 = MyTimer() >>> t1 Traceback (most recent call last): File "<pyshell#10>", line 1, in <module> t1 File "C:\Users\14158\AppData\Local\Programs\Python\Python37\lib\idlelib\rpc.py", line 617, in displayhook text = repr(value) File "C:\Users\14158\Desktop\lalallalalal.py", line 36, in __str__ return self.prompt AttributeError: 'MyTimer' object has no attribute 'prompt'
當直接執行t1的時候,Python會呼叫__str__()魔法方法,但它卻說這個類沒有prompt屬性。prompt屬性在哪裡定義的?在_calc()方法裡定義的,對不?但是沒有執行stop()方法,_calc()方法就沒有被呼叫到,所以也就沒有prompt屬性的定義了。
要解決這個問題也很簡單,大家應該還記得在類裡邊,用得最多的一個魔法方法是什麼?是__init__()嘛,所有屬於例項物件的變數只要在這裡邊先定義,就不會出現這樣的問題了。
def __init__(self): self.prompt = "未開始計時!" self.lasted = [] self.start = 0 self.stop = 0
>>> t1 = MyTimer() >>> t1 未開始計時! >>> t1.start() Traceback (most recent call last): File "<pyshell#16>", line 1, in <module> t1.start() TypeError: 'int' object is not callable
這裡又報錯了(當然是故意的),先檢查一下出現了什麼問題?
Python這裡丟擲了一個異常:TypeError: 'int' object is not callable
仔細瞧,在呼叫start()方法的時候報錯,也就是說,Python認為start是一個整型變數,而不是一個方法。為什麼呢?大家看__init__()方法裡,是不是也命名了一個叫做self.start的變數,如果類中的方法名和屬性同名,屬性會覆蓋方法。
好了,讓我們把self.start和self.stop都改為self.begin和self.end吧!
現在程式沒什麼問題了,但顯示的時間不怎麼好看,希望按章年月日時分秒來顯示,所以這裡新增一個列表用於存放對應的單位,然後再適當的地方增加溫馨提示:
import time as t class MyTimer: def __init__(self): self.unit = ['年', '月', '天', '小時', '分鐘', '秒'] self.prompt = "未開始計時!" self.lasted = [] self.begin = 0 self.end = 0 def __str__(self): return self.prompt __repr__ = __str__ def __add__(self, other): prompt = "總共執行了" result = [] for index in range(6): result.append(self.lasted[index] + other.lasted[index]) if result[index]: prompt += (str(result[index]) + self.unit[index]) return prompt # 開始計時 def start(self): self.begin = t.localtime() self.prompt = "提示:請先呼叫 stop() 停止計時!" print("計時開始...") # 停止計時 def stop(self): if not self.begin: print("提示:請先呼叫 start() 進行計時!") else: self.end = t.localtime() self._calc() print("計時結束!") # 內部方法,計算執行時間 def _calc(self): self.lasted = [] self.prompt = "總共執行了" for index in range(6): self.lasted.append(self.end[index] - self.begin[index]) if self.lasted[index]: self.prompt += (str(self.lasted[index]) + self.unit[index]) # 為下一輪計時初始化變數 self.begin = 0 self.end = 0
最後再寫一個魔法方法__add__(),讓兩個計時器物件相加會自動返回時間的和:
def __add__(self,other): prompt = "總共執行了" result = [] for index in range(6): result.append(self.lasted[index] + other.lasted[index]) if result[index]: prompt += (str(result[index]) + self.unit[index]) return prompt
>>> t1 = MyTimer() >>> t1 未開始計時! >>> t1.stop() 提示:請先呼叫 start() 進行計時! >>> t1.start() 計時開始... >>> t1 提示:請先呼叫 stop() 停止計時! >>> t1.stop() 計時結束! >>> t1 總共執行了7秒 >>> t2 = MyTimer() >>> t2.start() 計時開始... >>> t2.stop() 計時結束! >>> t1 + t2 '總共執行了18秒'
看上去程式碼不錯,也能正常計算了。但是這個程式還有幾點不足的地方:
(1)如果開始計時的時間是(2022年2月22日16:30:30),停止時間是(2025年1月23日15:30:30),那按照我們用停止時間減開始時間的計算方式就會出現負數(3年-1月1天-1小時),你應該對此做一些轉換。
(2)現在的計算機速度都非常快,而我們這個程式最小的計算單位卻只是秒,精度是遠遠不夠的。
*******************************
二、課時44課後習題及答案
*******************************