1. string:通用字符串操作
string模塊在很早的Python版本中就有了。以前這個模塊中提供的很多函數已經移植為str對象的方法,不過這個模塊仍保留了很多有用的常量和類來處理str對象。
1.1 常量
string.ascii_letters
下文所述ascii_lowercase和ascii_uppercase常量的拼接。該值不依賴於語言區域。
string.ascii_lowercase
小寫字母‘abcdefghijklmnopqrstuvwxyz’。此值不依賴於語言環境,並且不會更改。
string.ascii_uppercase
大寫字母‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’。此值不依賴於語言環境,並且不會更改。
string.digits
字符串‘0123456789’。
string.hexdigits
字符串‘0123456789abcdefABCDEF’。
string.octdigits
字符串‘01234567’
string.punctuation
ASCII字符的字符串,在C
區域設置中被視為標點符號。
string.printable
視為可打印的ASCII字符字符串。這是一個組合digits,ascii_letters,punctuation和whitespace。
string.whitespace
一個字符串,其中包含所有被視為空格的ASCII字符。這包括字符空格,制表符,換行符,返回符,換頁符和垂直制表符。
打印出string模塊中的常量:
import inspect import string def is_str(value): return isinstance(value, str) for name, value in inspect.getmembers(string, is_str): if name.startswith('_'): continue print('%s=%r\n' % (name, value))
結果:
這些常量在處理ASCII數據時很有用,但是由於以某種形式的Unicode遇到非ASCII文本越來越普遍,因此它們的應用受到限制。
1.2 自定義字符串格式化
Formatter類實現了與str的format()方法同樣的布局規范語言。它的功能包括類型強制,對齊,屬性和域引用、命名和位置模板參數以及特定於類型的格式設置選項。在大多數情況下,該format()方法都能更便利地訪問這些特功能,不過也可以利用Formatter構建子類,以備需要改動的情況。
class string.Formatter
Formatter類包含下列公有方法:
- format(format_string, /, *args, **kwargs)
- 首要的 API 方法。 它接受一個格式字符串和任意一組位置和關鍵字參數。 它只是一個調用vformat()的包裝器。
- 在 3.7 版更改: 格式字符串參數現在是僅限位置參數。
- vformat(format_string, args, kwargs)
-
此函數執行實際的格式化操作。 它被公開為一個單獨的函數,用於需要傳入一個預定義字母作為參數,而不是使用
*args
和**kwargs
語法將字典解包為多個單獨參數並重打包的情況。vformat()完成將格式字符串分解為字符數據和替換字段的工作。 它會調用下文所述的幾種不同方法。
此外,Formatter還定義了一些旨在被子類替換的方法:
- parse(format_string)
- 循環遍歷format_string並返回一個由可迭代對象組成的元組(literal_text, field_name, format_spec, conversion)。它會被vformat()用來將字符串分解為文本字面值或替換字段。
- 元組中的值在概念上表示一段字面文本加上一個替換字段。如果沒有字面文本(如果連續出現兩個替換字段就會發生這種情況),則literal_text將是一個長度為零的字符串。如果沒有替換字段,則field_name,format_spec和conversion的值將為None。
- get_field(field_name, args, kwargs)
- 給定 field_name 作為parse()的返回值,將其轉換為要格式化的對象。 返回一個元組 (obj, used_key)。 默認版本接受在 PEP 3101 所定義形式的字符串,例如 "0[name]" 或 "label.title"。args 和 kwargs 與傳給vformat()的一樣。返回值used_key與get_value()的 key 形參具有相同的含義。
- get_value(key, args, kwargs)
- 提取給定的字段值。 key 參數將為整數或字符串。 如果是整數,它表示 args 中位置參數的索引;如果是字符串,它表示kwargs中的關鍵字參數名。
- args 形參會被設為vformat()的位置參數列表,而kwargs形參會被設為由關鍵字參數組成的字典。
- 對於復合字段名稱,僅會為字段名稱的第一個組件調用這些函數;后續組件會通過普通屬性和索引操作來進行處理。
- 因此舉例來說,字段表達式 '0.name' 將導致調用get_value()時附帶key參數值0。在get_value()通過調用內置的getattr()函數返回后將會查找name屬性。
-
如果索引或關鍵字引用了一個不存在的項,則將引發
IndexError
或KeyError
。
- check_unused_args(used_args, args, kwargs)
- 在必要時實現對未使用參數進行檢測。 此函數的參數是是格式字符串中實際引用的所有參數鍵的集合(整數表示位置參數,字符串表示名稱參數),以及被傳給vformat的args和kwargs的引用。未使用參數的集合可以根據這些形參計算出來。如果檢測失敗則check_unused_args()應會引發一個異常。
- format_field(value, format_spec)
-
format_field()會簡單地調用內置全局函數format()。提供該方法是為了讓子類能夠重載它。
- convert_field(value, conversion)
- 使用給定的轉換類型(來自parse()方法所返回的元組)來轉換(由get_field()所返回的)值。默認版本支持's'(str),'r'(repr)和'a'(ascii)等轉換類型。
1.3 模板字符串
字符串模板是作為內置拼接語法的替代做法。使用string.Template拼接時,要在名字前加前綴$來標識變量(例如,${var}) 。
模板字符串支持基於$的替換,使用以下規則:
$$
為轉義符號;它會被替換為單個的$
。
$identifier
為替換占位符,它會匹配一個名為"identifier"
的映射鍵。在默認情況下,"identifier"
限制為任意 ASCII 字母數字(包括下划線)組成的字符串,不區分大小寫,以下划線或ASCII字母開頭。在$
字符之后的第一個非標識符字符將表明占位符的終結。
${identifier}
等價於$identifier
。當占位符之后緊跟着有效的但又不是占位符一部分的標識符字符時需要使用,例如"${noun}ification"
。
在字符串的其他位置出現$將導致引發ValueError。
class string.Template(template)
該構造器接受一個參數作為模板字符串。
- substitute(mapping={}, /, **kwds)
- 執行模板替換,返回一個新字符串。mapping為任意字典類對象,其中的鍵將匹配模板中的占位符。 或者你也可以提供一組關鍵字參數,其中的關鍵字即對應占位符。當同時給出mapping和kwds並且存在重復時,則以kwds中的占位符為優先。
- safe_substitute(mapping={}, /, **kwds)
-
類似於safe_substitute(),不同之處是如果有占位符未在mapping和kwds中找到,不是引發
KeyError
異常,而是將原始占位符不加修改地顯示在結果字符串中。另一個與substitute()的差異是任何在其他情況下出現的$
將簡單地返回$
而不是引發ValueError。 - 此方法被認為“安全”,因為雖然仍有可能發生其他異常,但它總是嘗試返回可用的字符串而不是引發一個異常。從另一方面來說,safe_substitute()也可能根本算不上安全,因為它將靜默地忽略錯誤格式的模板,例如包含多余的分隔符、不成對的花括號或不是合法Python標識符的占位符等等。
下面例子使用%操作符將簡單模板與相似的字符串插值進行比較,並使用來比較新格式的字符串語法str.format()。
import string values = {'var': 'foo'} t = string.Template(""" Variable : $var Escape : $$ Variable in text: ${var}iable """) print('TEMPLATE:', t.substitute(values)) s = """ Variable : %(var)s Escape : %% Variable in text: %(var)siable """ print('INTERPOLATION:', s % values) s = """ Variable : {var} Escape : {{}} Variable in text: {var}iable """ print('FORMAT:', s.format(**values))
在前兩種情況下,觸發字符($
或%
)通過重復兩次來進行轉義。在格式化語法中,需要重復{
和}
來轉義。
結果:
模板與字符串拼接或格式化的一個關鍵區別是,它不考慮參數的類型。值會轉換為字符串,而將字符串插入結果中。這里沒有提供格式化選項。例如,無法控制使用幾位有效數字來表示一個浮點值。
但是,這樣做的好處是,通過使用safe_substitute()方法,可以避免未能向模板提供所需的所有參數值時可能產生的異常。
import string values = {'var': 'foo'} t = string.Template("$var is here but $missing is not provided") try: print('substitute() :', t.substitute(values)) except KeyError as err: print('ERROR:', str(err)) print('safe_substitute():', t.safe_substitute(values))
由於value字典中沒有missing的值,所以substitute()會產生一個KeyError。safe_substitute()則不同,它不會拋出這個錯誤,而是會捕捉這個錯誤並保留文本中的變量表達式。
結果:
進階用法:你可以派生Template的子類來自定義占位符語法、分隔符,或用於解析模板字符串的整個正則表達式。 為此目的,你可以重載這些類屬性:
delimiter -- 這是用來表示占位符的起始的分隔符的字符串字面值。 默認值為 $
。 請注意此參數 不能 為正則表達式,因為其實現將在必要時對此字符串調用 re.escape()
。 還要注意你不能在創建類之后改變此分隔符(例如在子類的類命名空間中必須設置不同的分隔符)。
idpattern -- 這是用來描述不帶花括號的占位符的模式的正則表達式。 默認值為正則表達式 (?a:[_a-z][_a-z0-9]*)
。 如果給出了此屬性並且 braceidpattern 為 None
則此模式也將作用於帶花括號的占位符。
注解:由於默認的 flags 為 re.IGNORECASE
,模式 [a-z]
可以匹配某些非 ASCII 字符。 因此我們在這里使用了局部旗標 a
。
在 3.7 版更改: braceidpattern 可被用來定義對花括號內部和外部進行區分的模式。
braceidpattern -- 此屬性類似於 idpattern 但是用來描述帶花括號的占位符的模式。 默認值 None
意味着回退到 idpattern (即在花括號內部和外部使用相同的模式)。 如果給出此屬性,這將允許你為帶花括號和不帶花括號的占位符定義不同的模式。
3.7 新版功能.
flags -- 將在編譯用於識別替換內容的正則表達式被應用的正則表達式旗標。 默認值為 re.IGNORECASE
。 請注意 re.VERBOSE
總是會被加為旗標,因此自定義的 idpattern 必須遵循詳細正則表達式的約定。
3.2 新版功能.
作為另一種選項,你可以通過重載類屬性 pattern 來提供整個正則表達式模式。 如果你這樣做,該值必須為一個具有四個命名捕獲組的正則表達式對象。 這些捕獲組對應於上面已經給出的規則,以及無效占位符的規則:
escaped -- 這個組匹配轉義序列,在默認模式中即
$$
。named -- 這個組匹配不帶花括號的占位符名稱;它不應當包含捕獲組中的分隔符。
braced -- 這個組匹配帶有花括號的占位符名稱;它不應當包含捕獲組中的分隔符或者花括號。
invalid -- 這個組匹配任何其他分隔符模式(通常為單個分隔符),並且它應當出現在正則表達式的末尾。
string.Template
可以通過調整用於在模板主體中查找變量名稱的正則表達式模式來更改其默認語法。一種簡單的方法是更改delimiter
和idpattern
類屬性。
import string class MyTemplate(string.Template): delimiter = '%' idpattern = '[a-z]+_[a-z]+' template_text = ''' Delimiter : %% Replaced : %with_underscore Ignored : %notunderscored ''' d = { 'with_underscore': 'replaced', 'notunderscored': 'not replaced', } t = MyTemplate(template_text) print('Modified ID pattern:') print(t.safe_substitute(d))
在這個例子中,替換規則已經改變,定界符是%而不是$,而且變量名中間的某個位置必須包含一個下划線。模式%notunderscored不會被替換為任何字符串,因此它不包含下划線字符。
結果:
要完成更復雜的修改,可以覆蓋pattern屬性並定義一個全新的正則表達式。所提供的模式必須包含4個命名組,分別捕獲轉義定界符、命名變量、加括號的變量名和不合法的定界符模式。
import string t = string.Template('$var') print(t.pattern.pattern)
t.pattern的值是一個已編譯正則表達式,不過可以通過它的pattern屬性得到原來的字符串。
結果:
下面這個例子定義了一個新模式以創建一個新的模板類型,這個使用{{var}}作為變量語法。
import re import string class MyTemplate(string.Template): delimiter = '{{' pattern = r''' \{\{(?: (?P<escaped>\{\{)| (?P<named>[_a-z][_a-z0-9]*)\}\}| (?P<braced>[_a-z][_a-z0-9]*)\}\}| (?P<invalid>) ) ''' t = MyTemplate(''' {{{{ {{var}} ''') print('MATCHES:', t.pattern.findall(t.template)) print('SUBSTITUTED:', t.safe_substitute(var='replacement'))
必須分別提供named和braced模式,盡管它們實際上是一樣的。
結果:
1.4 輔助函數
string.capwords(s,sep=None)
使用str.split()將參數拆分為單詞,使用str.capitalize()將單詞轉為大寫形式,使用str.join()將大寫的單詞進行拼接。 如果可選的第二個參數 sep 被省略或為None,則連續的空白字符會被替換為單個空格符並且開頭和末尾的空白字符會被移除,否則 sep 會被用來拆分和拼接單詞。
import string s = 'The quick brown fox jumped over the lazy dog.' print(s) print(string.capwords(s))
結果: