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))
結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/207111.html
標籤:Python
上一篇:C 可變引數函式的本質
