python_魔法方法(三):__str__()和__repr__()
阿新 • • 發佈:2018-11-04
使用python的魔法方法和time模組定製一個計時器的類
1.用time模組裡的localtime()方法獲取時間
2.time.localtime返回struct_time格式
3.表現你的類:__str__()和__repr__()
先來看下__str__()和__repr__()魔法方法
>>> class A(): def __str__(self): return "我在學習python" >>> a = A() >>> print(a) 我在學習python >>> a<__main__.A object at 0x0000000002F6AB70> >>> class B(): def __repr__(self): return "python要一起學習的" >>> b = B() >>> b python要一起學習的 >>> print(b) python要一起學習的
看到這裡知道要怎麼寫了嗎,如果還是比較蒙的,那就繼續往下看吧
首先用到一個time模組,我們先匯入time模組
其次是兩個功能,一個是開始時間,一個是結束時間:
>>> importtime as t >>> class MyTimer(): def start(self): self.start = t.localtime() print("計時開始。。。") 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__
來我們加上執行看下效果
>>> import time as t >>> class MyTimer(): def start(self): self.start = t.localtime() print("計時開始。。。") 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) def __str__(self): return self.prompt __repr__ = __str__ >>> t1 = MyTimer() >>> t1.start() 計時開始。。。 >>> t1.stop() 總共運行了000007 結束計時。。。 >>> t1 總共運行了000007
很不錯的,但是,如果使用者不按常理出牌,直接呼叫t1,那就報錯了
>>> t1 = MyTimer() >>> t1 Traceback (most recent call last): File "<pyshell#57>", line 1, in <module> t1 File "C:\Python36\lib\idlelib\rpc.py", line 617, in displayhook text = repr(value) File "<pyshell#51>", line 17, in __str__ return self.prompt AttributeError: 'MyTimer' object has no attribute 'prompt'
來我們先分析下,當直接執行t1的時候,python會呼叫__str__()魔法方法,但他卻沒有prompt屬性。prompt屬性在__calc()方法就沒有被呼叫到,所以也就沒有prompt屬性的定義了。
需要解決這個問題,需要用到在類裡用到最多的方法__init__(),所有屬於例項物件的變數只要在這裡先定義,就不會出現這樣的問題了
>>> import time as t >>> class MyTimer(): def __init__(self): self.prompt = '未開始計時' self.lasted = 0 self.start = 0 self.stop = 0 def start(self): self.start = t.localtime() print("計時開始。。。") 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) def __str__(self): return self.prompt __repr__ = __str__ >>> t1 = MyTimer() >>> t1 未開始計時 >>> t1.start() Traceback (most recent call last): File "<pyshell#71>", line 1, in <module> t1.start() TypeError: 'int' object is not callable
這裡跑出的錯誤,異常是:
TypeError: 'int' object is not callable。在呼叫start()方法的時候報錯,看一下是不是在__init__()方法裡定義的self.start的變數和類中的方法名屬性同名,屬性會被覆蓋方法。所以這就是問題所在,那就修改過來吧,吧self.start和self.stop改成self.begin和self.end,這樣程式就沒有問題了,但是現實時間為000007這樣還是不太人性化,然後我們需要哪找年月日,值為0時不顯示的原則,讓人看著舒服
>>> import time as t >>> class MyTimer(): def __init__(self): self.unit =['年','月','天','小時','分鐘','秒'] self.prompt = '未開始計時' self.lasted = [] self.begin = 0 self.end = 0 def start(self): self.begin = t.localtime() print("計時開始。。。") def stop(self): 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]) self.prompt += (str(self.lasted[index]) + self.unit[index]) print(self.prompt) def __str__(self): return self.prompt __repr__ = __str__ >>> t1 = MyTimer() >>> t1.start() 計時開始。。。 >>> t1.stop() 總共運行了0年0月0天0小時0分鐘5秒 結束計時。。。
看似可以了,在加上一些溫馨提示的就很好了,總程式
1 import time as t 2 class MyTimer(): 3 def __init__(self): 4 self.unit =['年','月','天','小時','分鐘','秒'] 5 self.prompt = '未開始計時' 6 self.lasted = [] 7 self.begin = 0 8 self.end = 0 9 10 #開始計時 11 def start(self): 12 self.begin = t.localtime() 13 self.prompt = "提示;請先呼叫stop()結束計時" 14 print("計時開始。。。") 15 16 #停止計時 17 def stop(self): 18 if not self.begin: 19 print("提示:請先呼叫start()開始計時") 20 else: 21 self.end = t.localtime() 22 self.__calc() 23 print("結束計時。。。") 24 25 #計算執行時間 26 def __calc(self): 27 self.lasted = [] 28 self.prompt ="總共運行了" 29 for index in range(6): 30 self.lasted.append(self.end[index] - self.begin[index]) 31 if self.lasted[index]: 32 self.prompt += (str(self.lasted[index]) + self.unit[index]) 33 #為下一計算初始化變數 34 self.begin = 0 35 self.end = 0 36 print(self.prompt) 37 38 def __add__(self,other): 39 prompt = "總共運行了" 40 result = [] 41 for index in range(6): 42 result.append(self.lasted[index]+other.lasted[index]) 43 if result[index]: 44 prompt += (str(self.lasted[index]) + self.unit[index]) 45 return prompt 46 47 def __str__(self): 48 return self.prompt 49 __repr__ = __str__
結果:
>>> t1 = MyTimer() >>> t1 未開始計時 >>> t1.stop() 提示:請先呼叫start()開始計時 >>> t1.start() 計時開始。。。 >>> t1 提示;請先呼叫stop()結束計時 >>> t1.stop <bound method MyTimer.stop of 提示;請先呼叫stop()結束計時> >>> t1.stop() 總共運行了1分鐘 結束計時。。。 >>> t1 總共運行了1分鐘>>> t2 = MyTimer() >>> t2.start() 計時開始。。。 >>> t2.stop() 總共運行了5秒 結束計時。。。 >>> t2 總共運行了5秒 >>> t1+t2 '總共運行了1分鐘'