2.2. string — 字符串常量和模板
目的:包含用来处理文本的常量和类
string
模块可以追溯到 Python 最早的版本。这里面的很多方法都已转移到 str
对象中。本章将专注于 string
模块保留的一些用来处理 str
对象的常量和类。
函数
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.
模板
字符串模板是在 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))
前两种情况,触发字符($
和 %
)需要重复两次来转义。对于第三种格式化语法,{
和 }
都需要重复才能转义。
$ 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
上面三种方法的一个关键不同点是:没有考虑参数的类型。这些值被转换成字符串,然后插入到结果当中,没有可用的格式化选项。例如,无法控制用来表示浮点数的数字的个数。
然而,使用 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))
因为在 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))
在这个示例里,替换规则进行了变更,分隔符用 %
来替代了 $
并且变量名字中必须包含下划线。 %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
)
这个示例定义了一个新的模式来生成一种新的模板,使用 {{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
类的执行效果与 str
的format()
方法一致,它的特征包括型态转换,排列,属性以及字段引用,已命名特定位置的模板参数, 以及特定类型的格式化选项。通常 format()
方法对于这些特征是最便捷的接口,但 Formatter
提供了建立子类的方法,在需要多态情况下使用。
常量
string
模块包含了与 ASCII 、数字字符相关的一系列常量。
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 类型的非 ASCII 文本,在这个情况下的这些常量的作用就很有限了。
$ 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'
参见如下
- 标准库中的字符串文档
- 字符串方法 --
str
对象中用来取代string
功能的方法- PEP 292 -- 简便的字符串替代方法
- 格式化字符串语法 --
Formatter
和str.format()
的布局规范语言的正式定义
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。