Python Cookbook 第二版 漢化版 [Recipe 1.9] 簡化字符串 translate 方法的用法

Recipe 1.9. Simplifying Usage of Strings' translate Method
Recipe 1.9. 簡化字符串 translate 方法的用法


Credit: Chris Perkins, Raymond Hettinger


問題

您常常希望使用高效的字符串 translate 方法,但卻很難記住該方法和 string.maketrans 函數的詳細用法,因此您想要一種能在通常情況下簡化其用法的包裝方案(facade)。


解法

正如 Recipe 1.10 中所述,字符串的 translate 方法非常強大切頗具伸縮性。然而恰恰是因爲這種強大威力和可伸縮性所帶來的使用難度,使得我們似乎有必要使用一種“包裝方案(facade)”爲其添加一個前端接口,以便簡化其在通常情況下的用法:

import string
def translator(frm='', to='', delete='', keep=None):
    if len(to) == 1:
        to = to * len(frm)
    trans = string.maketrans(frm, to)
    if keep is not None:
        allchars = string.maketrans('', '')
        delete = allchars.translate(allchars, keep.translate(allchars, delete))
    def translate(s):
        return s.translate(trans, delete)
    return translate


討論

我常常發現自己想要使用字符串的 translate 方法來做些事情,但每次我都不得不停下來仔細回想其詳細用法(請參見 Recipe 1.10 查看更多關於詳細用法的信息)。因此我自己編寫了一個 class(之後又將其重製爲 factory closure ,即本條目“解法”中所呈現的方案),將多種可能的處理封裝到一個較爲簡易的 facade 當中。現如今,若我想要一個函數,使其只保留給定集合中的字符,我就可以簡單地建構並使用這個函數:

>>> digits_only = translator(keep=string.digits)
>>> digits_only('Chris Perkins : 224-7992')
'2247992'

若要從字符串中移除某個字符集中的字符,也同樣簡單:

>>> no_digits = translator(delete=string.digits)
>>> no_digits('Chris Perkins : 224-7992')
'Chris Perkins : -'

若要用單一個字符替換一個字符集合,可以這樣做:

>>> digits_to_hash = translator(from=string.digits, to='#')
>>> digits_to_hash('Chris Perkins : 224-7992')
'Chris Perkins : ###-####'

雖然上面這個用法可能看起來有點特殊,但於我而言確爲時不時就會出現的任務。

在本條目中,我不得不作出一個帶有隨意性的設計決定,即在 delete 參數與 keep 參數交疊的情況下,讓 delete 參數“吃掉”keep 參數:

>>> trans = translator(delete='abcd', keep='cdef')
>>> trans('abcdefg')
'ef'

對於您自己的應用而言,在指定了 keep 的情況下,或許忽略 delete 更好;而在兩者同時被指定的情況下,或許最好是拋出異常(因爲在同一個 translator 調用中同時指定兩者畢竟沒有多大實際意義)。同樣,如 Recipe 1.8 和 Recipe 1.10 所述,本條目中的代碼僅適用於普通字符串,不適用於 Unicode 字符串,因爲 Unicode 字符串的 translate 方法與普通字符串(即以 byte 爲處理單位的字符串)的同名方法有所區別。

---- BOX BEGIN ----
Closures

Closure 並沒有複雜到可怕的地步:它只是一個“內部”函數,指代“包含該函數的那個‘外部’函數的本地名稱(即變量)”。下面是個陽春的例子:

def make_adder(addend):
    def adder(augend): return augend+addend
    return adder

執行 p = make_adder(23) 就會製造出一個 closure ,即內部函數 adder ,其指代一個被綁定爲數值 23 的名稱。接着,q = make_adder(42) 又製造出一個 closure ,其內的 addend 被綁定到數值 42。此時 q 與 互不干涉,兩者可以愉快且獨立地共生。如此一來,我們就可以執行諸如 pprint p(100), q(100) 這樣的語句,並得到結果爲 123 142 的輸出。

在實際當中,您可能常常會看到,make_adder 會被看作 closure ,而不是以帶有學究氣的、生硬冗長的“返回 closure 的函數”來解釋。幸運的是,上下文經常能夠明晰具體情況。將 make_adder 稱爲 factory (或 factory function ,工廠函數)既準確又精煉;您還可以說它是 closure factory ,以便闡明它建造並返回 closures 的事實,而不是 class 或 class instances 。
---- BOX E N D ----


請參見

Recipe 1.10 包括本條目中 translate(keep=...) 的等價方案、更多關於 translate 方法的信息,以及適用於 Unicode 字符串的等價方案;在 Library ReferencePython in a Nutshell 中關於字符串 translate 方法以及 string 模塊中的 maketrans 函數的文檔。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章