1. 程式人生 > 實用技巧 >Python 中的運算子過載

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 語言對操作符過載的一些限制性規則。

這些限制性規則有:

  1. 不允許建立新的運算子,只能過載已有的那些運算子
  2. 不允許過載已有資料型別(如 tuple 、 string 、 list)的某些運算子操作
  3. 某些運算子不能過載,例如 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
大家一起來學習討論吧!