字符串常量和模板

字符串常量和模板#

函数#

string.capwords() 将字符串中所有单词的首字母大写。

import string

s = 'This tutorial provides an introduction to TVM, meant to address user who is new to the TVM project.'

print(s)
print(string.capwords(s))
This tutorial provides an introduction to TVM, meant to address user who is new to the TVM project.
This Tutorial Provides An Introduction To Tvm, Meant To Address User Who Is New To The Tvm Project.

警告

这个函数对全大写的单词也做了改变。

模板#

字符串模板是在 PEP 292 中作为可供选择的内置插入语法添加进来的。

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

通过例子来对比下:

  1. 模板插入

import string

values = {'var': 'foo'}

t = string.Template("""
Variable        : $var
Escape          : $$
Variable in text: ${var}iable
""")

print('TEMPLATE:', t.substitute(values))
TEMPLATE: 
Variable        : foo
Escape          : $
Variable in text: fooiable

使用 % 操作符的格式化语法

s = """
Variable        : %(var)s
Escape          : %%
Variable in text: %(var)siable
"""

print('INTERPOLATION:', s % values)
INTERPOLATION: 
Variable        : foo
Escape          : %
Variable in text: fooiable

使用 str.format() 的字符串语法

s = """
Variable        : {var}
Escape          : {{}}
Variable in text: {var}iable
"""

print('FORMAT:', s.format(**values))
FORMAT: 
Variable        : foo
Escape          : {}
Variable in text: fooiable

前两种情况,触发字符($%)需要重复两次来转义。对于第三种格式化语法,{} 都需要重复才能转义。

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

高级模板#

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

  Delimiter : %
  Replaced  : replaced
  Ignored   : %notunderscored

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

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

import string

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
            )
            

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

t.pattern
re.compile(r'\n            \$(?:\n              (?P<escaped>\$)  |   # Escape sequence of two delimiters\n              (?P<named>(?a:[_a-z][_a-z0-9]*))       |   # delimiter and a Python identifier\n              {(?P<braced>(?a:[_a-z][_a-z0-9]*))} |   # delimiter and a braced identifier\n              (?P<invalid>)             # Other ill-formed delimiter exprs\n            )\n            ',
           re.IGNORECASE|re.UNICODE|re.VERBOSE)

示例定义了新的模式来生成新的模板,使用 {{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 两个模式都必须单独提供,虽然它们都是一样的。

格式化程序#

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

常量#

string 模块包含了与 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'

这些常量在处理 ASCII 数据时是非常有效的,但是现在大家会越来越多的遇到 Unicode 类型的非 ASCII 文本,在这个情况下的这些常量的作用就很有限了。