---
# System prepended metadata

title: Python Magic Method __geitem__、 __setitem__

---

# 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**