Python中的魔術方法
本文將說明Python中的魔術方法。
YouTube Video
Python中的魔術方法
Python中的魔術方法(特殊方法)是一種具特殊命名規則的方法,用於賦予類別獨特的行為。例如,它們的特點是在前後皆有兩個底線(稱為 dunder),如__init__與__str__。因此,這類方法也被稱為「dunder方法」。
通過定義魔術方法,可以自訂類別的標準行為。例如,通過定義__add__可以改變+運算子的行為。
初始化與字串表示的魔術方法
__init__:初始化方法
__init__方法是在產生實例時自動呼叫的建構子。
1class Person:
2 def __init__(self, name, age):
3 self.name = name
4 self.age = age
5
6person = Person("Alice", 30)
7print(person.name) # Alice__str__:適合人類閱讀的字串表示
__str__方法會回傳易於人類閱讀的字串表示方式。這個方法會在print()和str()時被呼叫。
1class Person:
2 def __init__(self, name):
3 self.name = name
4
5 def __str__(self):
6 return f"Person: {self.name}"
7
8person = Person("Bob")
9print(person) # Person: Bob__repr__:用於除錯的字串表示
__repr__方法會回傳方便除錯的字串表示。這個方法會被repr()或解譯器顯示物件時呼叫。
1class Person:
2 def __init__(self, name):
3 self.name = name
4
5 def __repr__(self):
6 return f"Person(name={self.name!r})"
7
8person = Person("Eve")
9print(repr(person)) # Person(name='Eve')運算子多載的方法
__add__:+運算子
利用魔術方法可以對算術運算子進行多載。例如,__add__方法能多載+運算子。
1class Vector:
2 def __init__(self, x, y):
3 self.x = x
4 self.y = y
5
6 def __add__(self, other):
7 return Vector(self.x + other.x, self.y + other.y)
8
9 def __repr__(self):
10 return f"Vector({self.x}, {self.y})"
11
12 # Other arithmetic magic methods:
13 # def __sub__(self, other): # Subtraction (-)
14 # def __mul__(self, other): # Multiplication (*)
15 # def __truediv__(self, other): # True division (/)
16 # def __floordiv__(self, other): # Floor division (//)
17 # def __mod__(self, other): # Modulo (%)
18 # def __pow__(self, other): # Exponentiation (**)
19
20v1 = Vector(1, 2)
21v2 = Vector(3, 4)
22print(v1 + v2) # Vector(4, 6)其他算術相關的魔術方法還包括:。
| 方法 | 運算子 |
|---|---|
__add__ |
+ |
__sub__ |
- |
__mul__ |
* |
__truediv__ |
/ |
__floordiv__ |
// |
__mod__ |
% |
__pow__ |
** |
自訂比較運算子的方法
也可以多載比較運算子。例如,__eq__方法能多載等號運算子。
1class Box:
2 def __init__(self, volume):
3 self.volume = volume
4
5 def __eq__(self, other):
6 return self.volume == other.volume
7
8 def __lt__(self, other):
9 return self.volume < other.volume
10
11 # Comparison magic methods:
12 # def __eq__(self, other): # Equal to (==)
13 # def __ne__(self, other): # Not equal to (!=)
14 # def __lt__(self, other): # Less than (<)
15 # def __le__(self, other): # Less than or equal to (<=)
16 # def __gt__(self, other): # Greater than (>)
17 # def __ge__(self, other): # Greater than or equal to (>=)
18
19b1 = Box(100)
20b2 = Box(200)
21
22print(b1 == b2) # False
23print(b1 < b2) # True另外還有以下魔術方法:。這些魔術方法定義了物件間的相等性或大小關係等比較運算。
| 運算子 | 魔術方法 |
|---|---|
== |
__eq__ |
!= |
__ne__ |
< |
__lt__ |
<= |
__le__ |
> |
__gt__ |
>= |
__ge__ |
容器型別的魔術方法
你可以建立行為類似串列或字典的類別。
__len__:取得元素個數
__len__方法是會回傳元素個數的魔術方法。
1class Basket:
2 def __init__(self, items):
3 self.items = items
4
5 def __len__(self):
6 return len(self.items)
7
8basket = Basket(["apple", "banana"])
9print(len(basket)) # 2__getitem__:用索引取得值
__getitem__方法會在用索引存取時被呼叫。
1class Basket:
2 def __init__(self, items):
3 self.items = items
4
5 def __getitem__(self, index):
6 return self.items[index]
7
8basket = Basket(["apple", "banana"])
9print(basket[1]) # banana__setitem__與__delitem__:寫入與刪除
__setitem__與__delitem__這兩個方法會在寫入或刪除項目時被呼叫。
1class Basket:
2 def __init__(self, items):
3 self.items = items
4
5 def __setitem__(self, index, value):
6 self.items[index] = value
7
8 def __delitem__(self, index):
9 del self.items[index]
10
11basket = Basket(["apple", "banana"])
12basket[1] = "grape"
13del basket[0]
14print(basket.items) # ['grape']可疊代的魔術方法
要讓物件能在for迴圈中疊代,需要實作以下方法:。
__iter__與__next__
1class Counter:
2 def __init__(self, limit):
3 self.limit = limit
4 self.current = 0
5
6 def __iter__(self):
7 return self
8
9 def __next__(self):
10 if self.current >= self.limit:
11 raise StopIteration
12 self.current += 1
13 return self.current
14
15for num in Counter(3):
16 print(num)
17# Output:
18# 1
19# 2
20# 3脈絡管理器(with語句)
只要定義__enter__與__exit__,就能自訂with語句的前置與後置處理。
1class FileOpener:
2 def __init__(self, filename):
3 self.filename = filename
4
5 def __enter__(self):
6 self.file = open(self.filename, 'r')
7 return self.file
8
9 def __exit__(self, exc_type, exc_val, exc_tb):
10 self.file.close()
11
12with FileOpener("example.txt") as f:
13 content = f.read()
14 print(content)可呼叫物件:__call__
定義__call__方法後,實例就像函式一樣可以被呼叫。
1class Greeter:
2 def __init__(self, greeting):
3 self.greeting = greeting
4
5 def __call__(self, name):
6 return f"{self.greeting}, {name}!"
7
8hello = Greeter("Hello")
9print(hello("Alice")) # Hello, Alice!總結
Python的魔術方法可以為類別加入直觀且強大的自然行為。每個方法都有明確的用途,妥善實作可以讓你的程式更加彈性且更有Python風格。
魔術方法就像『隱形介面』,支撐著Python物件之間的互動和幕後運作。
您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。