CodeGym /課程 /Python SELF TW /操作符重載

操作符重載

Python SELF TW
等級 20 , 課堂 0
開放

6.1 魔法方法

在Python中,操作符重載允許為自定義類別定義或更改內建操作符(例如,+, -, *, /)的行為。 這是通過特殊的方法,也稱為魔法方法來實現的。

例如,你可以在自己的類別中重載比較操作符:

操作符 無底線的方法 方法簽名
== eq() __eq__(self, other)
!= ne() __ne__(self, other)
< lt() __lt__(self, other)
<= le() __le__(self, other)
> gt() __gt__(self, other)
>= ge() __ge__(self, other)

假設你編寫了一個類別,並想讓你的類別物件以你需要的方式進行比較。你只需在你的類別中實現「__eq__」方法,Python就會在每次代碼中比較你的類別物件時調用它。

示例:


class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
        
# 使用
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1 == v2)  # 輸出: True
print(v1 == v3)  # 輸出: False

每當你比較兩個您的物件時,Python會檢查他們是否實現了 函數 「__eq__」。如果有,就會調用它。如果沒有,則只是比較物件的引用。

實際上,上面的示例是寫著(只是還需加上檢查方法存在的句子):


# 使用
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1.__eq__(v2))  # 輸出: True
print(v1.__eq__(v3))  # 輸出: False

6.2 所有操作符列表

總共有6组操作符可以重載。

算術操作符:

操作符 無底線的方法 方法簽名
+ add __add__(self, other)
- sub __sub__(self, other)
* mul __mul__(self, other)
/ truediv __truediv__(self, other)
// floordiv __floordiv__(self, other)
% mod __mod__(self, other)
** pow __pow__(self, other)

比較操作符:

操作符 無底線的方法 方法簽名
== eq __eq__(self, other)
!= ne __ne__(self, other)
< lt __lt__(self, other)
<= le __le__(self, other)
> gt __gt__(self, other)
>= ge __ge__(self, other)

邏輯操作符:

操作符 無底線的方法 方法簽名
& and __and__(self, other)
| or __or__(self, other)
^ xor __xor__(self, other)
~ invert __invert__(self)

索引和切片操作符:

操作符 方法
obj[key] __getitem__(self, key)
obj[key] = value __setitem__(self, key, value)
del obj[key] __delitem__(self, key)

一元操作符:

操作符 方法
- __neg__(self)
+ __pos__(self)
abs() __abs__(self)
~ __invert__(self)

賦值操作符:

操作符 方法
+= __iadd__(self, other)
-= __isub__(self, other)
*= __imul__(self, other)
/= __itruediv__(self, other)
//= __ifloordiv__(self, other)
%= __imod__(self, other)
**= __ipow__(self, other)

可能這就是為什麼Python這麼慢 - 每次執行操作符之前,它都在查找類別及其所有父類別中的類似函數。不過這也使得代碼非常簡潔 :)

6.3 索引操作符

能夠比較物件或減去集合在某種意義上是顯而易見的。如果你編寫一個類別,並且這個類別預期會進行邏輯或數學運算,那麼你很容易想到這一點。

我想和你們分享一個有趣的例子——索引操作符。我們直接從示例代碼開始吧:


class CustomList:
    def __init__(self, data):
        self.data = data
        
    def __getitem__(self, index):
        return self.data[index]
        
    def __setitem__(self, index, value):
        self.data[index] = value
        
    def __delitem__(self, index):
        del self.data[index]
        
    def __repr__(self):
        return repr(self.data)
        
# 使用
c_list = CustomList([1, 2, 3, 4, 5])
print(c_list[1])  # 輸出: 2
c_list[1] = 10
print(c_list)  # 輸出: [1, 10, 3, 4, 5]
del c_list[1]
print(c_list)  # 輸出: [1, 3, 4, 5]

這裡我們看到三個操作的示例:

  • 通過索引讀取數據
  • 通過索引寫入數據
  • 甚至通過索引刪除數據。

而且內部的數據完全不必以列表的形式存儲。或者說索引不一定非得是數字。例如,類別dictionary(字典)就是這樣實現的。

創建SuperList

還記得類別list嗎?它允許你設置元素,但僅限於已有的索引。我們來創建一個自己的類別,叫做SuperList,這個類別可以用任何索引訪問元素:

  • 如果索引小於0,則將元素插入到開頭
  • 如果索引大於等於len,則將元素添加到末尾
  • 其餘情況下,只是返回該元素

示例:


class SuperList(list):
    def __init__(self, value):
        super().__init__(value)
        
    def __setitem__(self, index, value):
        if index >= len(self):
            super().append(value)
        elif index < 0:
            super().insert(0, value)
        else:
            super().__setitem__(index, value)
        
lst = SuperList([1, 2, 3])
lst[200] = 100
lst[-200] = 99
print(lst)  # [99, 1, 2, 3, 100]

所以,重載索引是一個很棒的功能,我建議在實踐中好好利用它。那麼今天就到這裡。

2
任務
Python SELF TW, 等級 20, 課堂 0
上鎖
重載比較運算子
重載比較運算子
2
任務
Python SELF TW, 等級 20, 課堂 0
上鎖
重載索引運算符
重載索引運算符
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION