Python3標準庫:string通用字符串操做

1. string:通用字符串操做

string模塊在很早的Python版本中就有了。之前這個模塊中提供的不少函數已經移植爲str對象的方法,不過這個模塊仍保留了不少有用的常量和類來處理str對象。git

1.1 常量

string.ascii_letters正則表達式

  下文所述ascii_lowercase和ascii_uppercase常量的拼接。該值不依賴於語言區域。api

string.ascii_lowercase數組

  小寫字母‘abcdefghijklmnopqrstuvwxyz’。此值不依賴於語言環境,而且不會更改。安全

string.ascii_uppercaseapp

  大寫字母‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’。此值不依賴於語言環境,而且不會更改。ide

string.digits函數

  字符串‘0123456789’。佈局

string.hexdigitsui

  字符串‘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屬性。
  若是索引或關鍵字引用了一個不存在的項,則將引起 IndexErrorKeyError
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能夠經過調整用於在模板主體中查找變量名稱的正則表達式模式來更改其默認語法一種簡單的方法是更改delimiteridpattern類屬性。

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))

結果:

相關文章
相關標籤/搜索