天天看點

《Python Cookbook(第2版)中文版》——1.16 替換字元串中的子串

本節書摘來自異步社群《python cookbook(第2版)中文版》一書中的第1章,第1.16節,作者[美]alex martelli , anna martelli ravenscrof , david ascher ,高鐵軍 譯,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

任務

需要一個簡單的方法來完成這樣一個任務:給定一個字元串,通過查詢一個替換字典,将字元串中被标記的子字元串替換掉。

解決方案

下面給出的解決辦法既适用于python 2.3,也适用于2.4:

如果參數safe是false,則預設條件下,字元串中所有被标記的子字元串必須能夠在字典d中找到,否則,expand會抛出一個keyerror異常并終止執行。當參數safe被明确指定為true時,如果被标記的子字元串在字典中找不到,則被标記的部分也不會被改變。

讨論

expand函數代碼的主體部分有個很有趣的地方:根據操作是否被要求為安全,它使用兩個不同的嵌套函數(兩者有着同樣的名字lookup)中的一個。安全意味着被标記的子字元串應該能夠在字典查到,如果查不到,不抛出keyerror異常。如果這個函數并不是必須安全的(預設情況下不安全),lookup根據索引通路字典d,并在該索引(子字元串)不存在的時候抛出個錯誤。但如果lookup被要求為安全的,它将使用d的方法get,get傳回根據索引能夠查到的值,若找不到就傳回在兩邊加上了标記的被查詢的子字元串。給safe傳入true,表明你甯可看到輸出中有标記符也不願看到異常資訊。marker+w+marker是可以替換w.join(marker*2)的另一種方式,但我采用後者的原因是,它展示了一種不太簡明卻很有意思的構造帶引号字元串的方法。

不管用哪個版本的lookup,expand都會執行切分、修改、拼接—這些在python的字元串進行中最重要的操作。在expand中進行修改的部分,使用了指定了步長的清單切片方法。确切地說,expand通路并重新綁定了parts的奇數索引的項,因為這些項正好是原字元串中位于兩個标記符之間的部分。是以,它們就是被标記的子字元串,也就是需要在字典中查找的字元串。

本節解決方案給出的expand函數接受非常靈活的字元串文法形式,比基于$的string.template更靈活。你如果想讓輸出字元串包括雙引号,也可以指定其他的标記符。當然,函數也沒有限制被标記的子串不能是辨別符,可以輕松地插入python表達式(d的 _getitem _方法會執行eval操作)或者任意其他占位符。而且,還可以輕易地搞出點有些不同的更有趣的效果,比如:

輸出結果是just one "little" test。進階使用者可以定制python 2.4的string.template類,通過繼承來實作上述的所有功能,甚至更多其他進階功能。但本節解決方案中的小巧的expand函數卻更加簡潔易用。