模塊目的:包含一些處理文本的常量和類
string
模塊可以追溯到Python的最初版本。該模塊原先的許多方法都被移植到了str
對象中,但是string
模塊依然保留了一些比較有用的常量和類,以便和str
對象搭配使用。本篇討論將着重關注string
模塊。
方法
capwords()
方法可以將一個字符串中的所有單詞轉換成其首字母大寫(其餘字母小寫)的形式。
# string_capwords.py
import string
s = 'The quick brown fox jumped over the lazy dog.'
print(s)
print(string.capwords(s))
轉換的結果和我們先用split()
分割,讓每個分割後的單詞首字母大寫,再調用join()
方法合併單詞的結果是一致的。
$ python3 string_capwords.py
The quick brown fox jumped over the lazy dog.
The Quick Brown Fox Jumped Over The Lazy Dog.
注:其實str
對象本身有一個title()
方法,與此效果是一致的。
模板
字符串模板作爲PEP 292的一部分被加入,並計劃成爲內置的字符串格式化的替代語法。使用string.Template
語法,變量使用前綴$
所標識(比如$var
),同時,如果需要與周圍的文本常量分隔開,也可以使用大括號將變量括起來(比如${var}
)。
下述示例比較了模板方法和我們熟悉的使用%
操作符的字符串格式化方法,以及較新的使用str.format()
的方法
# string_template.py
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))
在前兩個例子中,標識符$
和%
需要重複兩次來轉義。而對於format
語法,左括號{
和右括號}
也都需要重複兩次來轉義。
$ python3 string_template.py
TEMPLATE:
Variable : foo
Escape : $
Variable in text: fooiable
INTERPOLATION:
Variable : foo
Escape : %
Variable in text: fooiable
FORMAT:
Variable : foo
Escape : {}
Variable in text: fooiable
使用Template和其他字符串格式化方法的一個重要區別是我們無需考慮參數的類型。參數值會自動轉換成字符串類型,然後被插入結果字符串中。這裏也沒有額外的格式化選項,比如,我們沒有辦法去控制一個浮點型參數值的精度。
但是,一個額外的好處是,我們可以使用safe_substitute()
方法來避免所提供的參數值與參數不匹配帶來的異常。
# string_template_missing.py
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))
在這個例子中,參數值字典中沒有missing
這個值,所以substitute()
方法會引發一個KeyError
異常。而safe_substitute()
方法並不會引發異常,而是會捕獲它, 並將沒有匹配的參數表達式留在結果字符串中。
$ python3 string_template_missing.py
ERROR: 'missing'
safe_substitute(): foo is here but $missing is not provided
高級模板
string.Template
的默認語法規則可以通過調整它所使用的尋找變量名字的正則表達式來改變。一個簡單的可以實現這個效果的方法是,改變delimiter
和idpattern
這兩個類屬性。
# string_template_advanced.py
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))
在這個例子中,我們通過繼承string.Template
改變了置換規則,標識符變成了%
而不是$
,並且變量名字必須在中間某個地方包含下劃線_
。%notunderscored
變量沒有被替換,因爲該變量沒有包含下劃線_
。
$ python3 string_template_advanced.py
Modified ID pattern:
Delimiter : %
Replaced : replaced
Ignored : %notunderscored
對於更復雜的改變,我們可以重寫pattern
屬性並且定義一個全新的正則表達式。我們提供的正則表達式模式必須包含四個命名組,分別用來捕捉轉義的標識符、變量名、大括號括起來的變量名和不合法的定界模式。
# string_template_defaultpattern.py
import string
t = string.Template('$var')
print(t.pattern.pattern)
t.pattern
是一個編譯後的正則表達式,原始的正則字符串可以通過訪問它的pattern
屬性來得到。
\$(?:
(?P<escaped>\$) | # two delimiters
(?P<named>[_a-z][_a-z0-9]*) | # identifier
{(?P<braced>[_a-z][_a-z0-9]*)} | # braced identifier
(?P<invalid>) # ill-formed delimiter exprs
)
下述例子定義了一個新的正則模式,從而定義了一個新的Template,該Template使用{{var}}
來作爲變量匹配的語法規則。
# string_template_newsyntax.py
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
命名組需要都提供,即使它們是一樣的。運行上述樣例得到下面的輸出:
$ python3 string_template_newsyntax.py
MATCHES: [('{{', '', '', ''), ('', 'var', '', '')]
SUBSTITUTED:
{{
replacement
Formatter類
Formatter
與str
對象的format()
方法類似。在多數情況下,format()
方法更爲簡便,但是Formatter
類提供了一個建立子類的途徑。
常量
string
模塊包含了許多了常量和數字字符集合。
# string_constants.py
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編碼格式文本的流行,這些常量的作用也變得有限了。
$ python3 string_constants.py
ascii_letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
XYZ'
ascii_lowercase='abcdefghijklmnopqrstuvwxyz'
ascii_uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits='0123456789'
hexdigits='0123456789abcdefABCDEF'
octdigits='01234567'
printable='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ
RSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
punctuation='!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
whitespace=' \t\n\r\x0b\x0c'
參考:
1.string模塊的官方文檔
2.String方法 -str
對象的方法
3.PEP 292 - Simpler String Substitutions
4.格式化字符串語法規則 - 使用Formatter
和str.format()
的規範