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