Python 中的運算子過載
本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯絡我們以作處理
一種運算子對於不同型別的物件,有不同的使用方式。例如, +
用於整型物件,表示兩個數相加;用於字串,表示連線這兩個字串。
x, y = 10, 20
print(x + y) # 30
a,b = 'John', 'Wick'
print(a + b) # John Wick
複製程式碼
**+**
運算子因操作物件的型別的不同而執行不同的操作,這種特性稱為過載。
運算子的功能因其操作資料的型別而異,我們稱之為過載。
+
運算子可以用於任意兩個物件的相加嗎?我們來試試看。
class Vector: def __init__(self, x, y): self.x = x self.y = y v1 = Vector(3, 4) v2 = Vector(5, 6) v1 + v2 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-3-08104d7e1232> in <module> ----> 1 v1 + v2 TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector' 複製程式碼
執行這段程式碼會報錯。為什麼呢?這是因為 +
運算子不知道如何把兩個 Vector 類的物件相加。
在本文中,我們將研究如何將既有的運算子用於自定義物件的操作,同時我們要牢記 Python 語言對操作符過載的一些限制性規則。
這些限制性規則有:
- 不允許建立新的運算子,只能過載已有的那些運算子
- 不允許過載已有資料型別(如 tuple 、 string 、 list)的某些運算子操作
- 某些運算子不能過載,例如 is, or, and, not
在開始學習運算子過載前,我們需要了解 Python 資料模型 和 特殊方法。
Python 資料模型可以看作一種 “Python 設計方式”或 “Python 框架”。它告訴你 Python 如何管理物件以及如何對它們進行操作。它描述了一系列 API,你可以使用這些 API 使你定義的物件具備已有資料型別的某些功能,並且可以使用大多數 Python 語言的特性,而且不必實現它們。
特殊方法 → 當你使用 len(collection),Python 直譯器呼叫的是 collection.len() 方法。這裡的 len() 就是一個特殊方法。
特殊方法開頭和結尾都是 __ ,意為只能由 Python 直譯器呼叫,除非你在進行超程式設計,不然不要直接呼叫它。
在 Python 語言中,我們可以使用特殊方法來實現運算子過載。
現在我們進行編碼,使 Vector 物件支援 +
運算子。
當我們呼叫 **+**
這個運算子時,Python 直譯器呼叫了 add(self, other) 這個特殊方法。所以,在我們定義的類中實現 add() 方法,就可以支援 + 運算子。
class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Vector(self.x + other.x , self.y + other.y) def __repr__(self): return f'Vector({self.x}, {self.y})' v1 = Vector(3, 4) v2 = Vector(5, 6) v1 + v2 >>> Output: Vector(8, 10) 複製程式碼
你會發現,我們的類已經支援 +
運算子,在這個類中還實現了 repr() 方法,當我們呼叫 print() 方法,直譯器呼叫 str() 方法,如果我們沒有提供 repr() 的實現,就會呼叫原來的 repr() 方法。
注意:除了過載類似於 += 的賦值運算子外,一定要返回一個新建的物件。
再舉個過載運算子的例子
當我們使用 **==**
運算子時,Python 直譯器會呼叫 eq(self, other) 這個特殊方法,所以我們通過實現 eq() 方法就可以使某個類支援 ==
運算子。
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x , self.y + other.y)
def __repr__(self):
return f'Vector({self.x}, {self.y})'
def __eq__(self, other):
return self.x == other.x and self.y == other.y
v1 = Vector(3, 4)
v2 = Vector(5, 6)
v1 == v2
>>> Output: False
v3 = Vector(3,4)
v1 == v3
>>> Output: True
複製程式碼
在 Python 中,使用特殊方法可以輕鬆實現運算子過載。關鍵在於理解資料模型和特殊方法。
這些方法能讓你從 Python 的慣用特性中受益,並且能利用強大的標準庫。
欲瞭解 Python 資料模型的更多詳情,請參考 Fluent python。
這裡是 Python 中的特殊方法彙總,可供查閱。
總結
我們從理解什麼是運算子過載開始,接著討論了 Python 中運算子過載的一些限制條件、資料模型和特殊方法,然後在 Vector 類中實現了運算子過載。
希望你喜歡這篇文章。祝你工作順利,好運連連!
想要獲取更多Python學習資料可以加
QQ:2955637827私聊
或加Q群630390733
大家一起來學習討論吧!