python3-cookbook中每個小節以問題、解決方案和討論三個部分探討了Python3在某類問題中的最優解決方式,或者說是探討Python3本身的數據結構、函數、類等特性在某類問題上如何更好地使用。這本書對於加深Python3的使用和提升Python編程能力的都有顯著幫助,特別是對怎麼提高Py ...
python3-cookbook中每個小節以問題、解決方案和討論三個部分探討了Python3在某類問題中的最優解決方式,或者說是探討Python3本身的數據結構、函數、類等特性在某類問題上如何更好地使用。這本書對於加深Python3的理解和提升Python編程能力的都有顯著幫助,特別是對怎麼提高Python程式的性能會有很好的幫助,如果有時間的話強烈建議看一下。
本文為學習筆記,文中的內容只是根據自己的工作需要和平時使用寫了書中的部分內容,並且文中的示例代碼大多直接貼的原文代碼,當然,代碼都在Python3.6的環境上都驗證過了的。有興趣的可以去看全文。
python3-cookbook:https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html
2.1 使用多個界定符分割字元串
一般字元串的分割用str.split足以勝任,但是在複雜的文本中查找分割字元串,正則表達式是無疑是首選的工具,re模塊也有一個分割字元串的函數split,需要註意的是正則表達式中如果有括弧分組的話,分組的結果也會在結果列表中。
>>> import re >>> line = 'asdf fjdk; afed, fjek,asdf, foo' >>> re.split(r'[;,\s]\s*', line) ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo'] >>> fields = re.split(r'(;|,|\s)\s*', line) # 分組的內容也會出現在結果里 >>> fields ['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo'] >>>
2.3 用Shell通配符匹配字元串
當字元串的匹配一般方法不能滿足,但又不想用正則表達式那麼複雜,可以考慮使用fnmatch.fnmatch或fnmatch.fnmatchcase,兩者都可以使用Unix Shell中常用的通配符匹配字元串,區別在於前者使用的是操作系統的大小寫敏感規則,後者則完全按照你寫的內容去匹配。
>>> from fnmatch import fnmatch, fnmatchcase >>> fnmatch('foo.txt', '*.txt') True >>> fnmatch('foo.txt', '?oo.txt') True >>> fnmatch('Dat45.csv', 'Dat[0-9]*') True >>>
2.13 字元串對齊
字元串對齊是字元串格式化的一部分,對於普通的左對齊,右對齊和居中對齊可以使用字元串的ljust、rjust和center方法,也可以使用內置的format函數和字元串的format方法,文中推薦使用format,因為後者在字元串的格式化功能上更加的豐富和強大。
字元串的對齊工作中似乎並不常用,但我遇到過一個使用場景,就是使用字元串表示的二進位數時,需要用0或1來將字元串補齊為8位或者16位的字元串,這時字元串的對齊功能就排上用場了。
>>> text = 'Hello World' >>> text.ljust(20) 'Hello World ' >>> text.rjust(20) ' Hello World' >>> text.center(20) ' Hello World ' >>> text.rjust(20, '=') '=========Hello World' >>> text.center(20, '*') '****Hello World*****' >>>
>>> # 格式化字元串 >>> format(text, '>20') ' Hello World' >>> format(text, '<20') 'Hello World ' >>> format(text, '^20') ' Hello World ' >>> format(text, '=<20s') 'Hello World=========' >>> format(text, '*^20s') '****Hello World*****' >>> # 格式化數字 >>> x = 1.2345 >>> format(x, '^10.2f') ' 1.23 ' >>> # 字元串的format方法 >>> '{:>10s} {:>10s}'.format('Hello', 'World') ' Hello World'
2.16 以指定列寬格式化字元串
這個問題在列印信息或者在終端展示信息的時候可能會遇到,此時可以使用textwrap來指定輸出列寬。
>>> import textwrap >>> s = "Look into my eyes, look into my eyes, the eyes, the eyes, the eyes, not around the eyes, don't look around the eyes, look into my eyes, you're under." >>> print(textwrap.fill(s, 70)) Look into my eyes, look into my eyes, the eyes, the eyes, the eyes, not around the eyes, don't look around the eyes, look into my eyes, you're under. >>> print(textwrap.fill(s, 40)) Look into my eyes, look into my eyes, the eyes, the eyes, the eyes, not around the eyes, don't look around the eyes, look into my eyes, you're under. >>> print(textwrap.fill(s, 40, initial_indent=' ')) Look into my eyes, look into my eyes, the eyes, the eyes, the eyes, not around the eyes, don't look around the eyes, look into my eyes, you're under. >>> print(textwrap.fill(s, 40, subsequent_indent=' ')) Look into my eyes, look into my eyes, the eyes, the eyes, the eyes, not around the eyes, don't look around the eyes, look into my eyes, you're under. >>>
2.17 在字元串中處理html和xml
在處理HTML或XML文本的時候,想要將如&entity;或&#code;替換為對應的文本,或者反過來操作,只需要使用對應解析器的工具函數即可,當然,如果你比較熟悉對應的解析器的話或許有更好的方法。
>>> import html >>> s = 'Elements are written as "<tag>text</tag>".' >>> print(s) Elements are written as "<tag>text</tag>". >>> print(html.escape(s)) Elements are written as "<tag>text</tag>". >>> print(html.escape(s, quote=False)) Elements are written as "<tag>text</tag>". >>> >>> from html.parser import HTMLParser >>> s = 'Spicy "Jalapeño".' >>> p = HTMLParser() >>> p.unescape(s) 'Spicy "Jalapeño".' >>> >>> from xml.sax.saxutils import unescape >>> t = 'The prompt is >>>' >>> unescape(t) 'The prompt is >>>' >>>
2.18 字元串令牌解析
令牌化字元串可以使用正則表達式的命名捕獲分組來進行,語法為“(?P<group_name>)”,這個問題在解析用戶自定義的計算公式字元串時會很有用。
解決這個問題時,可以考慮使用模式對象的scanner方法,並打包到一個生成器中使用。
import re NAME = r'(?P<NAME>[a-zA-Z_][a-zA-Z_0-9]*)' NUM = r'(?P<NUM>\d+)' PLUS = r'(?P<PLUS>\+)' TIMES = r'(?P<TIMES>\*)' EQ = r'(?P<EQ>=)' WS = r'(?P<WS>\s+)' master_pat = re.compile('|'.join([NAME, NUM, PLUS, TIMES, EQ, WS])) scanner = master_pat.scanner('foo = 42') for m in iter(scanner.match, None): print(m.lastgroup, m.group())
NAME foo WS EQ = WS NUM 42