跳转至

6.1.string

Windows 10
Python 3.7.3 @ MSC v.1915 64 bit (AMD64)

Template

string.Template 中,通过前置 $ 来识别变量(例如,$var)。另外,如果有需要,可以通过大括号将它们从周围的文本中分开(例如,${var})。

通过例子来对比下:

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))
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() 方法可以带来一个好处,那就是如果模板需要的值没有全部作为参数提供给模板的话可以避免发生异常。

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))
ERROR: 'missing'
safe_substitute(): foo is here but $missing is not provided

因为在 values 字典中没有值提供给 missing , 所以 substitute() 会抛出一个 KeyError 异常。而 safe_substitute() 将捕捉这个异常并将变量表达式单独留在文本中而不是抛出异常。

string.Template 缺省语法可以通过改变正则表达式模式来调整,这个正则表达式一般是用来寻找模板内容内变量名字的。 简单的方法是通过改变 delimiteridpattern 的类属性来做调整。

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))
Modified ID pattern:

  Delimiter : %
  Replaced  : replaced
  Ignored   : %notunderscored

在这个示例里,替换规则进行了变更,分隔符用 % 来替代了 $ 并且变量名字中必须包含下划线。 %notunderscored 模式并没有被替换,因为它不包括下划线字符。

对于更复杂的改变,可以通过覆写 pattern 属性和定义一个全新的正则表达式来实现。覆写的模式必须提供四个命名组来获取未识别的分隔符、命名的变量、大括号模式的变量名称、和无效的分隔符模式。

t.pattern 的值是编译好的正则表达式,但是原始字符串可以通过它的 pattern 属性来获取

t = string.Template('$var')
print(t.pattern.pattern)
    \$(?:
      (?P<escaped>\$) |   # Escape sequence of two delimiters
      (?P<named>(?a:[_a-z][_a-z0-9]*))      |   # delimiter and a
Python identifier
      {(?P<braced>(?a:[_a-z][_a-z0-9]*))}  |   # delimiter and a
braced identifier
      (?P<invalid>)              # Other ill-formed delimiter exprs
    )

下面的示例定义了一个新的模式来生成一种新的模板,使用 {{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'))
MATCHES: [('{{', '', '', ''), ('', 'var', '', '')]
SUBSTITUTED:
{{
replacement

namedbraced 两个模式都必须单独提供,虽然它们都是一样的。

Formatter

Formatter 类的执行效果与 strformat() 方法一致,它的特征包括型态转换,排列,属性以及字段引用,已命名特定位置的模板参数, 以及特定类型的格式化选项。通常 format() 方法对于这些特征是最便捷的接口,但 Formatter 提供了建立子类的方法,在需要多态情况下使用。

常量

string 模块包含了与 ASCII 、数字字符相关的一系列常量。这些常量在处理 ASCII 数据时是非常有效的,但是现在大家会越来越多的遇到 Unicode 类型的非 ASCII 文本,在这个情况下的这些常量的作用就很有限了。

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_letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

ascii_lowercase='abcdefghijklmnopqrstuvwxyz'

ascii_uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

digits='0123456789'

hexdigits='0123456789abcdefABCDEF'

octdigits='01234567'

printable='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~
\t\n\r\x0b\x0c'

punctuation='!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

whitespace=' \t\n\r\x0b\x0c'