# Python Magic Method
如有錯誤歡迎糾正,小弟正在學習中
## ``__geitem__、 __setitem__`` Magic Method
### ``__getitem__``
定義: __getitem__ 是一個 Python 魔法方法(或稱為特殊方法),用於實現對象的索引訪問。當你使用索引(例如 obj[index])訪問對象的元素時,Python 會自動調用 __getitem__ 方法。
用途: 它允許你自定義對象的索引操作行為。你可以控制如何從對象中檢索數據。
``` python
class MyList:
def __init__(self, data):
self.data = data
def __getitem__(self, index):
return self.data[index]
# 使用
my_list = MyList([1, 2, 3])
print(my_list[1]) # 輸出:2
```
### ``__setitem__``
定義: __setitem__ 是另一個 Python 魔法方法,用於設置對象中某個索引位置的值。當你使用索引(例如 obj[index] = value)來賦值時,Python 會調用 __setitem__ 方法。
用途: 它允許你自定義如何設置對象的值。你可以控制如何將數據寫入對象。
``` python
class MyList:
def __init__(self, size):
self.data = [None] * size
def __setitem__(self, index, value):
self.data[index] = value
# 使用
my_list = MyList(3)
my_list[1] = 5
print(my_list.data) # 輸出:[None, 5, None]
```
### 使用場景
透過[]語法糖特性,可以對數據進行操作,常用場景如下:
- 需要自訂義Data container
- 配置設置
例子1: 定義了書櫃Class 可以實例書櫃與設置書櫃總層數。
參考文獻:[1]
``` python
class CustomBookshelf(object):
def __init__(self, layout_size):
self.book_list = [None] * layout_size
def __setitem__(self, key, value):
self.book_list[key] = value
return 1
def __getitem__(self, item):
return self.book_list[item]
bookshelf = CustomBookshelf(5)
bookshelf[0] = 'Python相關書籍'
bookshelf[1] = '設計模式相關書籍'
bookshelf[2] = '系統設計相關書籍'
bookshelf[3] = '演算法與資料結構書籍'
print(bookshelf[3])
>>> 演算法與資料結構書籍
```
例子2 自訂義2*2矩陣
``` python
class Matrix:
def __init__(self, rows, cols):
self.data = [[0] * cols for _ in range(rows)]
def __getitem__(self, index):
row, col = index
return self.data[row][col]
def __setitem__(self, index, value):
row, col = index
self.data[row][col] = value
matrix = Matrix(2, 2)
matrix[0, 1] = 5
print(matrix[0, 1]) # 輸出:5
```
例子3 配置管理Class
``` python
class Config:
def __init__(self, initial_config):
self.config = initial_config
def __getitem__(self, key):
return self.config.get(key)
def __setitem__(self, key, value):
self.config[key] = value
# 使用配置類
app_config = Config({'host': 'localhost', 'port': 8080})
print(app_config['host']) # 輸出:localhost
app_config['port'] = 9090
print(app_config['port']) # 輸出:9090
```
### 為何不定義function?
看到這邊你會想那為何不用function就好,接下來探討這個問題。
例子4
``` python
class CustomBookshelf:
def __init__(self, size):
self.books = [None] * size
def get_book(self, index):
return self.books[index]
def set_book(self, index, book):
self.books[index] = book
shelf = CustomBookshelf(5)
shelf.set_book(0, 'Python Programming')
print(shelf.get_book(0)) # 輸出:Python Programming
```
可以發現使用function上更清晰意圖更容易維護,對於index意義上可能模糊不清。
## 總結
使用__getitem__與__setitem__有以下點好處
### 優點
- 自訂義容器與內建數據結構操作一致(list、dict),某種程度上值觀易懂。
- 可直接用索引或者用切片處理數據簡化了程式。(例子2)
- 簡潔了呼叫function透過index做操作,而無須call function。
- 內部數據結構對外部使用者隱藏,提供了一個接口來操作數據,從而增強了數據封裝性。(例子2 初始2*2矩陣,但隱藏實作細節)
### 缺點
- 維護性上index意義上會模糊不清,可能會帶來維護上的困難
例子1 index意義可能不值觀,index 0 到底是第1層還是第0層? 現實中也沒有第0層定義。
- __getitem__ 和 __setitem__ 等魔術方法可能帶來的隱晦複雜性,對於不熟悉開發者可能需要了解用意。
參考文獻:
**[1]stackoverflow- "Understanding __getitem__ method in Python" https://stackoverflow.com/questions/43627405/understanding-getitem-method-in-python**