# 5.6.?專用類方法
* 5.6.1\. 獲得和設置數據項
除了普通的類方法,Python 類還可以定義專用方法。專用方法是在特殊情況下或當使用特別語法時由 Python 替你調用的,而不是在代碼中直接調用 (像普通的方法那樣)。
就像你在[上一節](userdict.html "5.5.?探索 UserDict:一個封裝類")所看到的,普通的方法對在類中封裝字典很有幫助。但是只有普通方法是不夠的,因為除了對字典調用方法之外,還有很多事情可以做的。例如,你可以通過一種沒有包括明確方法調用的語法來[獲得](../native_data_types/index.html#odbchelper.dict.define "例?3.1.?定義 Dictionary")和[設置](../native_data_types/index.html#odbchelper.dict.modify "例?3.2.?修改 Dictionary")數據項。這就是專用方法產生的原因:它們提供了一種方法,可以將非方法調用語法映射到方法調用上。
## 5.6.1.?獲得和設置數據項
## 例?5.12.?`__getitem__` 專用方法
```
def __getitem__(self, key): return self.data[key]
```
```
>>> f = fileinfo.FileInfo("/music/_singles/kairo.mp3")
>>> f
{'name':'/music/_singles/kairo.mp3'}
>>> f.__getitem__("name")
'/music/_singles/kairo.mp3'
>>> f["name"]
'/music/_singles/kairo.mp3'
```
| | |
| --- | --- |
| \[1\] | `__getitem__` 專用方法很簡單。像普通的方法 `clear`,`keys` 和 `values` 一樣,它只是重定向到字典,返回字典的值。但是怎么調用它呢?哦,你可以直接調用 `__getitem__`,但是在實際中你其實不會那樣做:我在這里執行它只是要告訴你它是如何工作的。正確地使用 `__getitem__` 的方法是讓 Python 來替你調用。 |
| \[2\] | 這個看上去就像你用來[得到一個字典值](../native_data_types/index.html#odbchelper.dict.define "例?3.1.?定義 Dictionary")的語法,事實上它返回你期望的值。下面是隱藏起來的一個環節:暗地里,Python 已經將這個語法轉化為 `f.__getitem__("name")` 的方法調用。這就是為什么 `__getitem__` 是一個專用類方法的原因,不僅僅是你可以自已調用它,還可以通過使用正確的語法讓 Python 來替你調用。 |
當然,Python 有一個與 `__getitem__` 類似的 `__setitem__` 專用方法,參見下面的例子。
## 例?5.13.?`__setitem__` 專用方法
```
def __setitem__(self, key, item): self.data[key] = item
```
```
>>> f
{'name':'/music/_singles/kairo.mp3'}
>>> f.__setitem__("genre", 31)
>>> f
{'name':'/music/_singles/kairo.mp3', 'genre':31}
>>> f["genre"] = 32
>>> f
{'name':'/music/_singles/kairo.mp3', 'genre':32}
```
| | |
| --- | --- |
| \[1\] | 與 `__getitem__` 方法一樣,`__setitem__` 簡單地重定向到真正的字典 `self.data` ,讓它來進行工作。并且像 `__getitem__` 一樣,通常你不會直接調用它,當你使用了正確的語法,Python 會替你調用 `__setitem__` 。 |
| \[2\] | 這個看上去像正常的字典語法,當然除了 `f` 實際上是一個類,它盡可能地打扮成一個字典,并且 `__setitem__` 是打扮的一個重點。這行代碼實際上暗地里調用了 `f.__setitem__("genre", 32)`。 |
`__setitem__` 是一個專用類方法,因為它可以讓 Python 來替你調用,但是它仍然是一個類方法。就像在 `UserDict` 中定義 `__setitem__` 方法一樣容易,我們可以在子類中重新定義它,對父類的方法進行覆蓋。這就允許我們定義出在某些方面像字典一樣動作的類,但是可以定義它自已的行為,超過和超出內置的字典。
這個概念是本章中我們正在學習的整個框架的基礎。每個文件類型可以擁有一個處理器類,這些類知道如何從一個特殊的文類型得到元數據。只要知道了某些屬性 (像文件名和位置),處理器類就知道如何自動地得到其它的屬性。它的實現是通過覆蓋 `__setitem__` 方法,檢查特別的關鍵字,然后當找到后加入額外的處理。
例如,`MP3FileInfo` 是 `FileInfo` 的子類。在設置了一個 `MP3FileInfo` 類的 `name` 時,并不只是設置 `name` 關鍵字 (像父類 `FileInfo` 所做的),它還要在文件自身內進行搜索 MP3 的標記然后填充一整套關鍵字。下面的例子將展示其工作方式。
## 例?5.14.?在 `MP3FileInfo` 中覆蓋 `__setitem__`
```
def __setitem__(self, key, item):
if key == "name" and item:
self.__parse(item)
FileInfo.__setitem__(self, key, item)
```
| | |
| --- | --- |
| \[1\] | 注意我們的 `__setitem__` 方法嚴格按照與父類方法相同的形式進行定義。這一點很重要,因為 Python 將替你執行方法,而它希望這個函數用確定個數的參數進行定義。(從技術上說,參數的名字沒有關系,只是個數。) |
| \[2\] | 這里就是整個 `MP3FileInfo` 類的難點:如果給 `name` 關鍵字賦一個值,我們還想做些額外的事情。 |
| \[3\] | 我們對 `name` 所做的額外處理封裝在了 `__parse` 方法中。這是定義在 `MP3FileInfo` 中的另一個類方法,則當我們調用它時,我們用 `self` 對其限定。僅是調用 `__parse` 將只會看成定義在類外的普通方法,調用 `self.__parse` 將會看成定義在類中的一個類方法。這不是什么新東西,你用同樣的方法來引用[數據屬性](userdict.html#fileinfo.userdict.normalmethods "例?5.10.?UserDict 常規方法")。 |
| \[4\] | 在做完我們額外的處理之后,我們需要調用父類的方法。記住,在 Python 中不會自動為你完成,需手工執行。注意,我們在調用直接父類,`FileInfo`,盡管它沒有 `__setitem__` 方法。沒問題,因為 Python 將會沿著父類樹走,直到它找到一個擁有我們正在調用方法的類,所以這行代碼最終會找到并且調用定義在 `UserDict` 中的 `__setitem__`。 |
> 注意
> 當在一個類中存取數據屬性時,你需要限定屬性名:`self._attribute_`。當調用類中的其它方法時,你屬要限定方法名:`self._method_`。
## 例?5.15.?設置 `MP3FileInfo` 的 `name`
```
>>> import fileinfo
>>> mp3file = fileinfo.MP3FileInfo()
>>> mp3file
{'name':None}
>>> mp3file["name"] = "/music/_singles/kairo.mp3"
>>> mp3file
{'album': 'Rave Mix', 'artist': '***DJ MARY-JANE***', 'genre': 31,
'title': 'KAIRO****THE BEST GOA', 'name': '/music/_singles/kairo.mp3',
'year': '2000', 'comment': 'http://mp3.com/DJMARYJANE'}
>>> mp3file["name"] = "/music/_singles/sidewinder.mp3"
>>> mp3file
{'album': '', 'artist': 'The Cynic Project', 'genre': 18, 'title': 'Sidewinder',
'name': '/music/_singles/sidewinder.mp3', 'year': '2000',
'comment': 'http://mp3.com/cynicproject'}
```
| | |
| --- | --- |
| \[1\] | 首先,我們創建了一個 `MP3FileInfo` 的實例,沒有傳遞給它文件名。(我們可以不用它,因為 `__init__` 方法的 `filename` 參數是[可選的](../power_of_introspection/optional_arguments.html "4.2.?使用可選參數和命名參數")。) 因為 `MP3FileInfo` 沒有它自已的 `__init__` 方法,Python 沿著父類樹走,發現了 `FileInfo` 的 `__init__` 方法。這個 `__init__` 方法手工調用了 `UserDict` 的 `__init__` 方法,然后設置 `name` 關鍵字為 `filename`,它為 `None`,因為我們還沒有傳入一個文件名。所以,`mp3file` 最初看上去像是有一個關鍵字的字典,`name` 的值為 `None`。 |
| \[2\] | 現在真正有趣的開始了。設置 `mp3file` 的 `name` 關鍵字觸發了 `MP3FileInfo` 上的 `__setitem__` 方法 (而不是 `UserDict` 的),這個方法注意到我們正在用一個真實的值來設置 `name` 關鍵字,接著調用 `self.__parse`。盡管我們完全還沒有研究過 `__parse` 方法,從它的輸出你可以看出,它設置了其它幾個關鍵字:`album`、`artist`、`genre`、`title`、`year` 和 `comment`。 |
| \[3\] | 修改 `name` 關鍵字將再次經受同樣的處理過程:Python 調用 `__setitem__`,`__setitem__`調用 `self.__parse`,`self.__parse` 設置其它所有的關鍵字。 |
- 版權信息
- 第?1?章?安裝 Python
- 1.1.?哪一種 Python 適合您?
- 1.2.?Windows 上的 Python
- 1.3.?Mac OS X 上的 Python
- 1.4.?Mac OS 9 上的 Python
- 1.5.?RedHat Linux 上的 Python
- 1.6.?Debian GNU/Linux 上的 Python
- 1.7.?從源代碼安裝 Python
- 1.8.?使用 Python 的交互 Shell
- 1.9.?小結
- 第?2?章?第一個 Python 程序
- 2.1.?概覽
- 2.2.?函數聲明
- 2.3.?文檔化函數
- 2.4.?萬物皆對象
- 2.5.?代碼縮進
- 2.6.?測試模塊
- 第?3?章?內置數據類型
- 3.1.?Dictionary 介紹
- 3.2.?List 介紹
- 3.3.?Tuple 介紹
- 3.4.?變量聲明
- 3.5.?格式化字符串
- 3.6.?映射 list
- 3.7.?連接 list 與分割字符串
- 3.8.?小結
- 第?4?章?自省的威力
- 4.1.?概覽
- 4.2.?使用可選參數和命名參數
- 4.3.?使用 type、str、dir 和其它內置函數
- 4.4.?通過 getattr 獲取對象引用
- 4.5.?過濾列表
- 4.6.?and 和 or 的特殊性質
- 4.7.?使用 lambda 函數
- 4.8.?全部放在一起
- 4.9.?小結
- 第?5?章?對象和面向對象
- 5.1.?概覽
- 5.2.?使用 from _module_ import 導入模塊
- 5.3.?類的定義
- 5.4.?類的實例化
- 5.5.?探索 UserDict:一個封裝類
- 5.6.?專用類方法
- 5.7.?高級專用類方法
- 5.8.?類屬性介紹
- 5.9.?私有函數
- 5.10.?小結
- 第?6?章?異常和文件處理
- 6.1.?異常處理
- 6.2.?與文件對象共事
- 6.3.?for 循環
- 6.4.?使用 `sys.modules`
- 6.5.?與目錄共事
- 6.6.?全部放在一起
- 6.7.?小結
- 第?7?章?正則表達式
- 7.1.?概覽
- 7.2.?個案研究:街道地址
- 7.3.?個案研究:羅馬字母
- 7.4.?使用 {n,m} 語法
- 7.5.?松散正則表達式
- 7.6.?個案研究:解析電話號碼
- 7.7.?小結
- 第?8?章?HTML 處理
- 8.1.?概覽
- 8.2.?sgmllib.py 介紹
- 8.3.?從 HTML 文檔中提取數據
- 8.4.?BaseHTMLProcessor.py 介紹
- 8.5.?locals 和 globals
- 8.6.?基于 dictionary 的字符串格式化
- 8.7.?給屬性值加引號
- 8.8.?dialect.py 介紹
- 8.9.?全部放在一起
- 8.10.?小結
- 第?9?章?XML 處理
- 9.1.?概覽
- 9.2.?包
- 9.3.?XML 解析
- 9.4.?Unicode
- 9.5.?搜索元素
- 9.6.?訪問元素屬性
- 9.7.?Segue [9]
- 第?10?章?腳本和流
- 10.1.?抽象輸入源
- 10.2.?標準輸入、輸出和錯誤
- 10.3.?查詢緩沖節點
- 10.4.?查找節點的直接子節點
- 10.5.?根據節點類型創建不同的處理器
- 10.6.?處理命令行參數
- 10.7.?全部放在一起
- 10.8.?小結
- 第?11?章?HTTP Web 服務
- 11.1.?概覽
- 11.2.?避免通過 HTTP 重復地獲取數據
- 11.3.?HTTP 的特性
- 11.4.?調試 HTTP web 服務
- 11.5.?設置 User-Agent
- 11.6.?處理 Last-Modified 和 ETag
- 11.7.?處理重定向
- 11.8.?處理壓縮數據
- 11.9.?全部放在一起
- 11.10.?小結
- 第?12?章?SOAP Web 服務
- 12.1.?概覽
- 12.2.?安裝 SOAP 庫
- 12.3.?步入 SOAP
- 12.4.? SOAP 網絡服務查錯
- 12.5.?WSDL 介紹
- 12.6.?以 WSDL 進行 SOAP 內省
- 12.7.?搜索 Google
- 12.8.? SOAP 網絡服務故障排除
- 12.9.?小結
- 第?13?章?單元測試
- 13.1.?羅馬數字程序介紹 II
- 13.2.?深入
- 13.3.?romantest.py 介紹
- 13.4.?正面測試 (Testing for success)
- 13.5.?負面測試 (Testing for failure)
- 13.6.?完備性檢測 (Testing for sanity)
- 第?14?章?測試優先編程
- 14.1.?roman.py, 第 1 階段
- 14.2.?roman.py, 第 2 階段
- 14.3.?roman.py, 第 3 階段
- 14.4.?roman.py, 第 4 階段
- 14.5.?roman.py, 第 5 階段
- 第?15?章?重構
- 15.1.?處理 bugs
- 15.2.?應對需求變化
- 15.3.?重構
- 15.4.?后記
- 15.5.?小結
- 第?16?章?函數編程
- 16.1.?概覽
- 16.2.?找到路徑
- 16.3.?重識列表過濾
- 16.4.?重識列表映射
- 16.5.?數據中心思想編程
- 16.6.?動態導入模塊
- 16.7.?全部放在一起
- 16.8.?小結
- 第?17?章?動態函數
- 17.1.?概覽
- 17.2.?plural.py, 第 1 階段
- 17.3.?plural.py, 第 2 階段
- 17.4.?plural.py, 第 3 階段
- 17.5.?plural.py, 第 4 階段
- 17.6.?plural.py, 第 5 階段
- 17.7.?plural.py, 第 6 階段
- 17.8.?小結
- 第?18?章?性能優化
- 18.1.?概覽
- 18.2.?使用 timeit 模塊
- 18.3.?優化正則表達式
- 18.4.?優化字典查找
- 18.5.?優化列表操作
- 18.6.?優化字符串操作
- 18.7.?小結
- 附錄?A.?進一步閱讀
- 附錄?B.?五分鐘回顧
- 附錄?C.?技巧和竅門
- 附錄?D.?示例清單
- 附錄?E.?修訂歷史
- 附錄?F.?關于本書
- 附錄 G. GNU Free Documentation License
- G.0. Preamble
- G.1.?Applicability and definitions
- G.2.?Verbatim copying
- G.3.?Copying in quantity
- G.4.?Modifications
- G.5.?Combining documents
- G.6.?Collections of documents
- G.7.?Aggregation with independent works
- G.8.?Translation
- G.9.?Termination
- G.10.?Future revisions of this license
- G.11.?How to use this License for your documents
- 附錄 H. GNU 自由文檔協議
- H.0. 序
- H.1.?適用范圍和定義
- H.2.?原樣復制
- H.3.?大量復制
- H.4.?修改
- H.5.?合并文檔
- H.6.?文檔合集
- H.7.?獨立著作聚集
- H.8.?翻譯
- H.9.?終止協議
- H.10.?協議將來的修訂
- H.11.?如何為你的文檔使用本協議
- 附錄 I. Python license
- I.A. History of the software
- I.B.?Terms and conditions for accessing or otherwise using Python
- 附錄 J. Python 協議
- J.0. 關于譯文的聲明
- J.A.?軟件的歷史
- J.B.?使用 Python 的條款和條件