Python Cookbook 第二版 漢化版 [Recipe 1.3] 測試一個對象是否爲 String-like 對象

Recipe 1.3. Testing Whether an Object Is String-like
Recipe 1.3. 測試一個對象是否爲 String-like 對象

Credit: Luther Blissett


問題

您需要一個對象(通常會作爲實參用於您正在撰寫的方法或函數)進行檢測,查看其是否爲字符串(更準確地說,是否爲 string-like 對象)。


解法

要檢查某對象是否爲字符串或 Unicode 對象,簡單快速的辦法是使用內建的 isinstancebasestring ,用法如下所示:

def isAString(anobj):
    return isinstance(anobj, basestring)


討論

針對本問題,許多程序員腦海中浮現出來的做法是類型檢測:

def isExactlyAString(anobj):
    return type(anobj) is type('')

然而這種做法相當糟糕,因爲它經意地破壞了 Python 最強大的能力之一,即平滑的、基於簽名式(signature)的多態機制。該解法中的測試無法處理 Unicode 對象、用戶編寫的 str 子類的實體,以及用戶編寫的任何 string-like 類型的實體。

本條目所推薦的“使用 isinstance 內建函數”的方案要好得多。內建類型 basestring 正是爲支持此方案而存在的。basestringstr unicode 類型的公共基類,用戶代碼中定義的任何 string-like 類型都應該以 basestring 作爲基類,以保證上述 isinstance 檢測能夠正常發揮效用。與 object 一樣,basestring 基本上是個“空”類型,因此繼承該類並無額外開銷。

不幸的是,諸如 Python 標準庫 UserString 模塊中 UserString 這樣的類,明顯是 string-like ,但卻無法被正兒八經的 isinstance 檢測所接受,因爲……唉……UserString 類沒有繼承自 basestring 。若您需要檢測這樣的類型是否爲 string-like ,您可以直接檢查該類型對象的行爲是否像一個字符串,例如:

def isStringLike(anobj):
    try: anobj + ''
    except: return False
    else: return True

isStringLike 函數比本條目解法中展示的 isAString 函數慢一些,也更爲複雜,但其確是既可以接受 UserString(以及其他 string-like 類型)的實體,也可以接受 str unicode 實體。

Python 中進行類型檢查(type-checking)的通用方案稱爲“duck typing”:若該類型的對象“走”起路來像鴨子,“叫”起來也像鴨子,於我們而言它就很像鴨子了。本條目中的 isStringLike 函數只能算是“叫”起來像鴨子,但可能足夠用了。若您需要檢查對象裏更多的 string-like 機能,可以通過 try 語句來完成,在 try 區塊中加入豐富的表達式來檢查更多的對象屬性,例如:

    try: anobj.lower( ) + anobj + ''

譯註:duck typing 是 Python、Ruby 等動態語言中常見的一種編程思想,其基本思想是:若某對象走起路來像鴨子,叫起來也像鴨子,那就當它是鴨子。考察對象類型時,不關心所面對的對象實際是什麼類型,只關心該對象能否完成我們期望其完成的任務;進行類型檢查時,不採用常規的、專門用於檢測類型的函數或方法(比如 isinstance() type()),而是通過檢查對象所包含的方法或屬性,來確定該對象能否完成期望的任務。換句話說,duck typing 強調的是類型的接口,而不是類型的內部詳情。貫徹此思想而編寫出來的設計良好的代碼,往往由於能夠支持“以多態方式來替換類型”,從而增強了代碼的可伸縮性。Dave Thomas 所著的 Programming Ruby: The Pragmatic Programmers' Guide, Second Edition 中的第 23 章專門討論了 duck typing ,可供參考。

然而以筆者的經驗來看,isStringLike 函數中的簡單測試通常能夠滿足筆者的需求。

對於類型驗證這樣的任務(甚至是任何其他驗證任務),最具 Pythonic 風味的做法就是直接嘗試完成任務,在遇到非法情形時,測出並處理任何可能導致的錯誤或異常——這種做法被稱爲“it's Easier to Ask Forgiveness than Permission(EAFP)”,意即“尋求體諒比尋求應允更容易。”實現 EAFP 風格的關鍵設施是 try/except 機制。有時候(比如本條目的情形),您可能會選擇一些簡單任務(比如與空字符串進行連接)來作爲對象中豐富的屬性集合(比如字符串對象所支持的豐富的操作和方法)的代言者,參與類型檢查。


請參見

Library ReferencePython in a Nutshell 一書中關於內建的 isinstancebasestring 的文檔。
 

發佈了134 篇原創文章 · 獲贊 7 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章