從一個加減法運算程式碼理解特殊運算子的過載

makesifriend發表於2017-11-29
class wow():
    def __init__(s,x):
        s.x = x
    def __add__(s,y):
        return wow(s.x+y.x)
    def __sub__(s,y):
        return wow(s.x-y.x)
    def __repr__(s):
        return str(s.x)
a=wow(5)
b=wow(7)
c=wow(3)
res=a-b+c
print(res)

在一個類中對特殊操作符的進行重新定義之後,這個類的例項關於這個操作符的運算就可以根據類中定義的方法進行操作。這種對操作符的重新定義也被稱為操作符的過載。
在python中,以雙下劃線開始和結束的函式定義(比如說__self__),就是對操作符或者函式的過載。上面的Python程式碼可以實現a,b,c之間的加減法運算,程式碼中的wow類對操作符“-,+,()”進行了重定義。之後關於wow的例項a,b,c中“-,+,repr函式”之間的運算就會以wow類中的方法進行操作。

以加法為例,在不對操作符進行過載的情況下,程式是不能實現兩個wow例項的直接相加的。對“+”進行了重定義後,這時,在對wow例項進行“+”操作相當於對例項中的兩個資料進行加法運算,最後,在將wow輸出的資料以wow例項的形式輸出(return wow(s.x+y.x))。這裡,在一個類的定義裡,實現了對兩個例項的操作。

str可以將結果以字串的形式顯示(如果本身資料就是字串,那麼就只需要按資料原來的樣子輸出就可以了);repr即使不被print呼叫,當需要顯示時也會把資料進行字串轉換。除了可以具有str的作用之外,repr還可以將不能轉化成字串的資料的記憶體讀出來。在使用print函式時,首先會呼叫str函式,如果print所處理的類沒有定義str,print就會嘗試呼叫repr。如果連repr都沒有,print輸出的東西就不知道輸出的是什麼了。可以通過下面兩個例子區分str,repr。
class wow(object):
def __init__(s,a):
s.x = a
def __str__(s):
return str(s.x)
a=wow(5)

在shell中輸入上面的python程式,然後直接輸a,結果顯示
“<main.wow object at 0x7fa93c00e2e8>”;
如果在shell中輸入print(a),結果就顯示整數5。

如果把上面python程式的str改成repr,即
def __repr__(s):
return repr(s.x)

此時無論直接輸入a,或者輸入print(a),結果都是整數5。

所以,從上面的例子可以看出:
1,如果類中只有對str的重定義,如果將a直接輸出,並不會呼叫到wow中的__str__
2,如果類中只對repr進行重定義,不管是直接輸出a,或是print(a)(因為沒有__str__,所以print會呼叫__repr__,都可以呼叫到__repr__,實現字串的轉換。(根據這一點,python reference講repr函式可以用於除錯,如何是這樣的,我現在還不能明白。關於repr的重定義
3,在開始的程式中,程式碼對repr進行重定義,使repr呼叫str函式。由於repr可以顯示資料時呼叫,然後在對資料進行str操作。所以如果在命令列中輸入a,也會顯示整數5。

相關文章