Python標準庫---1八、文本處理服務:string 常見的字符串操做

上一篇文章: Python標準庫---1七、內置異常
下一篇文章:

字符串常量

此模塊中定義的常量爲:git

  • string.ascii_letters

    下文所述 ascii_lowercase 和 ascii_uppercase 常量的拼連。 該值不依賴於語言區域。正則表達式

  • string.ascii_lowercase

    小寫字母 'abcdefghijklmnopqrstuvwxyz'。 該值不依賴於語言區域,不會發生改變。segmentfault

  • string.ascii_uppercase

    大寫字母 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'。 該值不依賴於語言區域,不會發生改變。api

  • string.digits

    字符串 '0123456789'。數組

  • string.hexdigits

    字符串 '0123456789abcdefABCDEF'。安全

  • string.octdigits

    字符串 '01234567'。app

  • string.punctuation

    由在 C 語言區域中被視爲標點符號的 ASCII 字符組成的字符串。ide

  • string.printable

    由被視爲可打印符號的 ASCII 字符組成的字符串。 這是 digits, ascii_letters, punctuation 和 whitespace 的總和。函數

  • string.whitespace

    由被視爲空白符號的 ASCII 字符組成的字符串。 其中包括空格、製表、換行、回車、進紙和縱向製表符。工具

自定義字符串格式化

內置的字符串類提供了經過使用 PEP 3101 所描述的 format() 方法進行復雜變量替換和值格式化的能力。 string 模塊中的 Formatter 類容許你使用與內置 format() 方法相同的實現來建立並定製你本身的字符串格式化行爲。

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) 等轉換類型。

格式字符串語法

str.format() 方法和 Formatter 類共享相同的格式字符串語法(雖然對於 Formatter 來講,其子類能夠定義它們本身的格式字符串語法)。 具體語法與 格式化字符串字面值 類似,但也存在區別。

格式字符串包含有以花括號 {} 括起來的「替換字段」。 不在花括號以內的內容被視爲字面文本,會不加修改地複製到輸出中。 若是你須要在字面文本中包含花括號字符,能夠經過重複來轉義: {{ and }}。

替換字段的語法以下:

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
    field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
    arg_name          ::=  [identifier | digit+]
    attribute_name    ::=  identifier
    element_index     ::=  digit+ | index_string
    index_string      ::=  <any source character except "]"> +
    conversion        ::=  "r" | "s" | "a"
    format_spec       ::=  <described in the next section>

用不太正式的術語來描述,替換字段開頭能夠用一個 field_name 指定要對值進行格式化並取代替換字符被插入到輸出結果的對象。 field_name 以後有可選的 conversion 字段,它是一個感嘆號 '!' 加一個 format_spec,並以一個冒號 ':' 打頭。 這些指明瞭替換值的非默認格式。

另請參閱 格式規格迷你語言 一節。

field_name 自己以一個數字或關鍵字 arg_name 打頭。 若是爲數字,則它指向一個位置參數,而若是爲關鍵字,則它指向一個命名關鍵字參數。 若是格式字符串中的數字 arg_names 爲 0, 1, 2, ... 的序列,它們能夠所有省略(而非部分省略),數字 0, 1, 2, ... 將會按順序自動插入。 因爲 arg_name 不使用引號分隔,所以沒法在格式字符串中指定任意的字典鍵 (例如字符串 '10' 或 ':-]')。 arg_name 以後能夠帶上任意數量的索引或屬性表達式。 '.name' 形式的表達式會使用 getattr() 選擇命名屬性,而 '[index]' 形式的表達式會使用 __getitem__() 執行索引查找。

在 3.1 版更改: 位置參數說明符對於 str.format() 能夠省略,所以 '{} {}'.format(a, b) 等價於 '{0} {1}'.format(a, b)。

在 3.4 版更改: 位置參數說明符對於 Formatter 能夠省略。

一些簡單的格式字符串示例

"First, thou shalt count to {0}"  # References first positional argument
"Bring me a {}"                   # Implicitly references the first positional argument
"From {} to {}"                   # Same as "From {0} to {1}"
"My quest is {name}"              # References keyword argument 'name'
"Weight in tons {0.weight}"       # 'weight' attribute of first positional arg
"Units destroyed: {players[0]}"   # First element of keyword argument 'players'.

使用 conversion 字段在格式化以前進行類型強制轉換。 一般,格式化值的工做由值自己的 __format__() 方法來完成。 可是,在某些狀況下最好強制將類型格式化爲一個字符串,覆蓋其自己的格式化定義。 經過在調用 __format__() 以前將值轉換爲字符串,能夠繞過正常的格式化邏輯。

目前支持的轉換旗標有三種: '!s' 會對值調用 str(),'!r' 調用 repr() 而 '!a' 則調用 ascii()。

幾個例子:

"Harold's a clever {0!s}"        # Calls str() on the argument first
"Bring out the holy {name!r}"    # Calls repr() on the argument first
"More {!a}"                      # Calls ascii() on the argument first

format_spec 字段包含值應如何呈現的規格描述,例如字段寬度、對齊、填充、小數精度等細節信息。 每種值類型能夠定義本身的「格式化迷你語言」或對 format_spec 的解讀方式。

大多數內置類型都支持一樣的格式化迷你語言,具體描述見下一節。

format_spec 字段還能夠在其內部包含嵌套的替換字段。 這些嵌套的替換字段可能包括字段名稱、轉換旗標和格式規格描述,可是再也不容許更深層的嵌套。 format_spec 內部的替換字段會在解讀 format_spec 字符串以前先被解讀。 這將容許動態地指定特定值的格式。

請參閱 格式示例 一節查看相關示例。

格式規格迷你語言

「格式規格」在格式字符串所包含的替換字段內部使用,用於定義單個值應如何呈現 (參見 格式字符串語法 和 格式化字符串字面值)。 它們也能夠被直接傳給內置的 format() 函數。 每種可格式化的類型均可以自行定義如何對格式規格進行解讀。

大多數內置類型都爲格式規格實現了下列選項,不過某些格式化選項只被數值類型所支持。

通常約定空格式字符串 ("") 將產生與對值調用 str() 相同的結果。 非空格式字符串一般會修改這一結果。

標準格式說明符 的通常形式以下:

format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
fill            ::=  <any character>
align           ::=  "<" | ">" | "=" | "^"
sign            ::=  "+" | "-" | " "
width           ::=  digit+
grouping_option ::=  "_" | ","
precision       ::=  digit+
type            ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

若是指定了一個有效的 align 值,則能夠在該值前面加一個 fill 字符,它能夠爲任意字符,若是省略則默認爲空格符。 在 格式化字符串字面值 或在使用 str.format() 方法時是沒法使用花括號字面值 ("{" or "}") 做爲 fill 字符的。 可是,經過嵌套替換字段插入花括號則是能夠的。 這個限制不會影響 format() 函數。

各類對齊選項的含義以下:

clipboard.png

請注意,除非定義了最小字段寬度,不然字段寬度將始終與填充它的數據大小相同,所以在這種狀況下,對齊選項沒有意義。

sign 選項僅對數字類型有效,能夠是如下之一:

clipboard.png

'#' 選項可讓「替代形式」被用於轉換。 替代形式可針對不一樣類型分別定義。 此選項僅對整數、浮點、複數和 Decimal 類型有效。 對於整數類型,當使用二進制、八進制或十六進制輸出時,此選項會爲輸出值添加相應的 '0b', '0o' 或 '0x' 前綴。 對於浮點數、複數和 Decimal 類型,替代形式會使得轉換結果老是包含小數點符號,即便其不帶小數。 一般只有在帶有小數的狀況下,此類轉換的結果中才會出現小數點符號。 此外,對於 'g' 和 'G' 轉換,末尾的零不會從結果中被移除。

',' 選項表示使用逗號做爲千位分隔符。 對於感應區域設置的分隔符,請改用 'n' 整數表示類型。

在 3.1 版更改: 添加了 ',' 選項 (另請參閱 PEP 378)。

'_' 選項表示對浮點表示類型和整數表示類型 'd' 使用下劃線做爲千位分隔符。 對於整數表示類型 'b', 'o', 'x' 和 'X',將爲每 4 個數位插入一個下劃線。 對於其餘表示類型指定此選項則將致使錯誤。

在 3.6 版更改: 添加了 '_' 選項 (另請參閱 PEP 515)。

width 是一個定義最小字段寬度的十進制整數。 若是未指定,則字段寬度將由內容肯定。

當未顯式給出對齊方式時,在 width 字段前加一個零 ('0') 字段將爲數字類型啓用感知正負號的零填充。 這至關於設置 fill 字符爲 '0' 且 alignment 類型爲 '='。

precision 是一個十進制數字,表示對於以 'f' and 'F' 格式化的浮點數值要在小數點後顯示多少個數位,或者對於以 'g' 或 'G' 格式化的浮點數值要在小數點先後共顯示多少個數位。 對於非數字類型,該字段表示最大字段大小 —— 換句話說就是要使用多少個來自字段內容的字符。 對於整數值則不容許使用 precision。

最後,type 肯定了數據應如何呈現。

可用的字符串表示類型是:
clipboard.png

可用的整數表示類型是:

clipboard.png

在上述的表示類型以外,整數還能夠經過下列的浮點表示類型來格式化 (除了 'n' 和 None)。 當這樣作時,會在格式化以前使用 float() 將整數轉換爲浮點數。

浮點數和小數值可用的表示類型有:

clipboard.png

格式示例

本節包含 str.format() 語法的示例以及與舊式 % 格式化的比較。

該語法在大多數狀況下與舊式的 % 格式化相似,只是增長了 {} 和 : 來取代 %。 例如,,'%03.2f' 能夠被改寫爲 '{:03.2f}'。

新的格式語法還支持新增的不一樣選項,將在如下示例中說明。

按位置訪問參數:

>>> '{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>> '{}, {}, {}'.format('a', 'b', 'c')  # 3.1+ only
'a, b, c'
>>> '{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>> '{2}, {1}, {0}'.format(*'abc')      # unpacking argument sequence
'c, b, a'
>>> '{0}{1}{0}'.format('abra', 'cad')   # arguments' indices can be repeated
'abracadabra'

按名稱訪問參數:

>>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
'Coordinates: 37.24N, -115.81W'
>>> coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
>>> 'Coordinates: {latitude}, {longitude}'.format(**coord)
'Coordinates: 37.24N, -115.81W'

訪問參數的屬性:

>>> c = 3-5j
>>> ('The complex number {0} is formed from the real part {0.real} '
...  'and the imaginary part {0.imag}.').format(c)
'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.'
>>> class Point:
...     def __init__(self, x, y):
...         self.x, self.y = x, y
...     def __str__(self):
...         return 'Point({self.x}, {self.y})'.format(self=self)
...
>>> str(Point(4, 2))
'Point(4, 2)'

訪問參數的項:

>>> coord = (3, 5)
>>> 'X: {0[0]};  Y: {0[1]}'.format(coord)
'X: 3;  Y: 5'

替代 %s 和 %r:

>>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
"repr() shows quotes: 'test1'; str() doesn't: test2"

對齊文本以及指定寬度:

>>> '{:<30}'.format('left aligned')
'left aligned                  '
>>> '{:>30}'.format('right aligned')
'                 right aligned'
>>> '{:^30}'.format('centered')
'           centered           '
>>> '{:*^30}'.format('centered')  # use '*' as a fill char
'***********centered***********'

替代 %+f, %-f 和 % f 以及指定正負號:

>>> '{:+f}; {:+f}'.format(3.14, -3.14)  # show it always
'+3.140000; -3.140000'
>>> '{: f}; {: f}'.format(3.14, -3.14)  # show a space for positive numbers
' 3.140000; -3.140000'
>>> '{:-f}; {:-f}'.format(3.14, -3.14)  # show only the minus -- same as '{:f}; {:f}'
'3.140000; -3.140000'

替代 %x 和 %o 以及轉換基於不一樣進位制的值:

>>> # format also supports binary numbers
>>> "int: {0:d};  hex: {0:x};  oct: {0:o};  bin: {0:b}".format(42)
'int: 42;  hex: 2a;  oct: 52;  bin: 101010'
>>> # with 0x, 0o, or 0b as prefix:
>>> "int: {0:d};  hex: {0:#x};  oct: {0:#o};  bin: {0:#b}".format(42)
'int: 42;  hex: 0x2a;  oct: 0o52;  bin: 0b101010'

使用逗號做爲千位分隔符:

>>> '{:,}'.format(1234567890)
'1,234,567,890'

表示爲百分數:

>>> points = 19
>>> total = 22
>>> 'Correct answers: {:.2%}'.format(points/total)
'Correct answers: 86.36%'

使用特定類型的專屬格式化:

>>> import datetime
>>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)
>>> '{:%Y-%m-%d %H:%M:%S}'.format(d)
'2010-07-04 12:15:58'

嵌套參數以及更復雜的示例:

>>> for align, text in zip('<^>', ['left', 'center', 'right']):
...     '{0:{fill}{align}16}'.format(text, fill=align, align=align)
...
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
>>>
>>> octets = [192, 168, 0, 1]
>>> '{:02X}{:02X}{:02X}{:02X}'.format(*octets)
'C0A80001'
>>> int(_, 16)
3232235521
>>>
>>> width = 5
>>> for num in range(5,12): 
...     for base in 'dXob':
...         print('{0:{width}{base}}'.format(num, base=base, width=width), end=' ')
...     print()
...
    5     5     5   101
    6     6     6   110
    7     7     7   111
    8     8    10  1000
    9     9    11  1001
   10     A    12  1010
   11     B    13  1011

模板字符串

模板字符串提供了由 PEP 292 所描述的更簡便的字符串替換方式。 模板字符串的一個主要用例是文本國際化 (i18n),由於在此場景下,更簡單的語法和功能使得文本翻譯過程比使用 Python 的其餘內置字符串格式化工具更爲方便。 做爲基於模板字符串構建以實現 i18n 的庫的一個示例,請參看 flufl.i18n 包。

模板字符串支持基於 $ 的替換,使用如下規則:

  • $$ 爲轉義符號;它會被替換爲單個的 $。

    • $identifier 爲替換佔位符,它會匹配一個名爲 "identifier" 的映射鍵。 在默認狀況下,"identifier" 限制爲任意 ASCII 字母數字(包括下劃線)組成的字符串,不區分大小寫,如下劃線或 ASCII 字母開頭。 在 $ 字符以後的第一個非標識符字符將代表佔位符的終結。
  • ${identifier} 等價於 $identifier。 當佔位符以後緊跟着有效的但又不是佔位符一部分的標識符字符時須要使用,例如 "${noun}ification"。

在字符串的其餘位置出現 $ 將致使引起 ValueError。

string 模塊提供了實現這些規則的 Template 類。 Template 有下列方法:

class string.Template(template)

該構造器接受一個參數做爲模板字符串。
  • substitute(mapping, **kwds)

    執行模板替換,返回一個新字符串。 mapping 爲任意字典類對象,其中的鍵將匹配模板中的佔位符。 或者你也能夠提供一組關鍵字參數,其中的關鍵字即對應占位符。 當同時給出 mapping 和 kwds 而且存在重複時,則以 kwds 中的佔位符爲優先。
  • safe_substitute(mapping, **kwds)

    相似於 substitute(),不一樣之處是若是有佔位符未在 mapping 和 kwds 中找到,不是引起 KeyError 異常,而是將原始佔位符不加修改地顯示在結果字符串中。 另外一個與 substitute() 的差別是任何在其餘狀況下出現的 $ 將簡單地返回 $ 而不是引起 ValueError。
    
       此方法被認爲「安全」,由於雖然仍有可能發生其餘異常,但它老是嘗試返回可用的字符串而不是引起一個異常。 從另外一方面來講,safe_substitute() 也可能根本算不上安全,由於它將靜默地忽略錯誤格式的模板,例如包含多餘的分隔符、不成對的花括號或不是合法 Python 標識符的佔位符等等。

    Template 的實例還提供一個公有數據屬性:

    • template

      這是做爲構造器的 template 參數被傳入的對象。 通常來講,你不該該修改它,但並不強制要求只讀訪問。

如下是一個如何使用模版的示例:

>>>

>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d)
Traceback (most recent call last):
...
ValueError: Invalid placeholder in string: line 1, col 11
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
...
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'

進階用法:你能夠派生 Template 的子類來自定義佔位符語法、分隔符,或用於解析模板字符串的整個正則表達式。 爲此目的,你能夠重載這些類屬性:

  • delimiter -- 這是用來表示佔位符的起始的分隔符的字符串字面值。 默認值爲 $。 請注意此參數 不能 爲正則表達式,由於其實現將在必要時對此字符串調用 re.escape()。 還要注意你不能在建立類以後改變此分隔符(例如在子類的類命名空間中必須設置不一樣的分隔符)。
  • idpattern -- 這是用來描述不帶花括號的佔位符的模式的正則表達式。 默認值爲正則表達式 (?a:_a-z*)。 若是給出了此屬性而且 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.capwords(s, sep=None)

使用 str.split() 將參數拆分爲單詞,使用 str.capitalize() 將單詞轉爲大寫形式,使用 str.join() 將大寫的單詞進行拼接。 若是可選的第二個參數 sep 被省略或爲 None,則連續的空白字符會被替換爲單個空格符而且開頭和末尾的空白字符會被移除,不然 sep 會被用來拆分和拼接單詞。
相關文章
相關標籤/搜索