1. 程式人生 > >python_魔法方法(三):__str__()和__repr__()

python_魔法方法(三):__str__()和__repr__()

使用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模組

其次是兩個功能,一個是開始時間,一個是結束時間:

>>> 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) >>> 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分鐘'