string --- 常見的字串操作

原始碼:Lib/string.py


字串常數

此模組中定義的常數為:

string.ascii_letters

下文描述的 ascii_lowercaseascii_uppercase 常數的串接,該值不依賴於區域設定。

string.ascii_lowercase

小寫字母 'abcdefghijklmnopqrstuvwxyz'。該值與地區設定無關且不會改變。

string.ascii_uppercase

大寫字母 ’ABCDEFGHIJKLMNOPQRSTUVWXYZ’。 此值與地區設定無關且不會改變。

string.digits

字串 ’0123456789’

string.hexdigits

字串 ’0123456789abcdefABCDEF’

string.octdigits

字串 '01234567'

string.punctuation

C 語言中被視為標點符號的 ASCII 字元的字串: !”#$%&’()*+,-./:;<=>?@[\]^_`{|}~

string.printable

ASCII 字元的字串是可被列印輸出的。 這是 digitsascii_letterspunctuationwhitespace 的組合。

string.whitespace

包含所有 ASCII 字元的字串都視為空白字元 (whitespace)。 包含空格 (space)、製表符號 (tab)、換行符號 (linefeed)、return、換頁符號 (formfeed) 和垂直製表符號 (vertical tab) 這些字元。

自訂字串格式

透過 PEP 3101 中描述的 format() 方法,內建字串類別提供了進行複雜變數替換和數值格式化的能力。string 模組中的 Formatter 類別模組可讓你使用與內建 format() 方法相同的實作來建立和自訂你自己的字串格式化行為。

class string.Formatter

Formatter 類別有以下的公開方法:

format(format_string, /, *args, **kwargs)

主要的 API 方法。它接收一個格式字串及一組任意的位置引數與關鍵字引數,是呼叫 vformat() 的包裝器 (wrapper)。

在 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_specconversion 的值将为 None

get_field(field_name, args, kwargs)

给定 field_name 作为 parse() (见上文) 的返回值,将其转换为要格式化的对象。 返回一个元组 (obj, used_key)。 默认版本接受在 PEP 3101 所定义形式的字符串,例如 "0[name]" 或 "label.title"。 argskwargs 与传给 vformat() 的一样。 返回值 used_keyget_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 的 argskwargs 的引用。 未使用参数的集合可以根据这些形参计算出来。 如果检测失败则 check_unused_args() 应会引发一个异常。

format_field(value, format_spec)

format_field() 会简单地调用内置全局函数 format()。 提供该方法是为了让子类能够重载它。

convert_field(value, conversion)

使用给定的转换类型(来自 parse() 方法所返回的元组)来转换(由 get_field() 所返回的)值。 默认版本支持 's' (str), 'r' (repr) 和 'a' (ascii) 等转换类型。

格式化文字語法

str.format() 方法和 Formatter 类共享相同的格式字符串语法(虽然对于 Formatter 来说,其子类可以定义它们自己的格式字符串语法)。 具体语法与 格式化字符串字面值 相似,但较为简单一些,并且关键的一点是不支持任意表达式。

格式字符串包含有以花括号 {} 括起来的“替换字段”。 不在花括号之内的内容被视为字面文本,会不加修改地复制到输出中。 如果你需要在字面文本中包含花括号字符,可以通过重复来转义: {{ and }}

替换字段的语法如下:

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
arg_name          ::=  [identifier | digit+]
attribute_name    ::=  identifier
element_index     ::=  digit+ | index_string
index_string      ::=  <any source character except "]"> +
conversion        ::=  "r" | "s" | "a"
format_spec       ::=  format-spec:format_spec

用不太正式的术语来描述,替换字段开头可以用一个 field_name 指定要对值进行格式化并取代替换字符被插入到输出结果的对象。 field_name 之后有可选的 conversion 字段,它是一个感叹号 '!' 加一个 format_spec,并以一个冒号 ':' 打头。 这些指明了替换值的非默认格式。

另請參閱 格式規格 (Format Specification) 迷你語言 部份。

field_name 本身以一个数字或关键字形式的 arg_name 打头。 如果为数字,则它指向一个位置参数,而如果为关键字,则它指向一个命名关键字参数。 如果在字符串上调用 str.isdecimal() 会返回真值则 arg_name 会被当作数字来处理。 如果格式字段串中的数字 arg_names 为 0, 1, 2, ... 的序列,它们可以全部(而非部分)被省略并且数字 0, 1, 2, ... 将按顺序被自动插入。 由于 arg_name 不使用引号分隔,因此无法在格式字符串中指定任意的字典键(例如字符串 '10'':-]' 等)。 arg_name 之后可以跟任意数量的索引或属性表达式。 '.name' 形式的表达式会使用 getattr() 来选择命名属性,而 '[index]' 形式的表达式会使用 __getitem__() 来执行索引查找。

在 3.1 版的變更: 位置参数说明符对于 str.format() 可以省略,因此 '{} {}'.format(a, b) 等价于 '{0} {1}'.format(a, b)

在 3.4 版的變更: 位置参数说明符对于 Formatter 可以省略。

一些简单的格式字符串示例

"First, thou shalt count to {0}"  # References first positional argument
"Bring me a {}"                   # Implicitly references the first positional argument
"From {} to {}"                   # Same as "From {0} to {1}"
"My quest is {name}"              # References keyword argument 'name'
"Weight in tons {0.weight}"       # 'weight' attribute of first positional arg
"Units destroyed: {players[0]}"   # First element of keyword argument 'players'.

conversion 字段会在格式化之前进行类型强制转换。 通常,格式化一个值的工作是由该值本身的 __format__() 方法完成的。 但是,在某些情况下最好是强制将类型格式化为一个字符串,覆盖其本身的格式化定义。 通过在调用 __format__() 之间将值转换为字符串,可以绕过正常的格式化逻辑。

目前支援三種轉換旗標:'!s' 會對該值呼叫 str()'!r' 會對該值呼叫 repr(),而 '!a' 則會對該值呼叫 ascii()

一些範例:

"Harold's a clever {0!s}"        # Calls str() on the argument first
"Bring out the holy {name!r}"    # Calls repr() on the argument first
"More {!a}"                      # Calls ascii() on the argument first

format_spec 欄位描述了值的呈現規格,例如欄位寬度、對齊、填充 (padding)、小數精度等細節資訊。每種值類型都可以定義自己的「格式化迷你語言 (formatting mini-language)」或對 format_spec 的解釋。

大多數內建型別都支援常見的格式化迷你語言,下一節將會詳細說明。

format_spec 欄位還可以在其內部包含巢狀的替換欄位。這些巢狀的替換欄位可能包含欄位名稱、轉換旗標、格式規格描述,但是不允許再更深層的巢狀結構。format_spec 内部的替換欄位會在 format_spec 字串被直譯前被替換。這讓數值的格式能夠被動態地指定。

範例請見 格式範例

格式規格 (Format Specification) 迷你語言

「格式規格」在格式字串 (format string) 中包含的替換欄位中使用,以定義各個值如何被呈現(請參考 格式化文字語法f-string(f 字串))。它們也能夠直接傳遞給內建的 format() 函式。每個可格式化型別 (formattable type) 可以定義格式規格如何被直譯。

大部分內建型別為了格式規格實作了下列選項,不過有些選項只被數值型別支援。

一般來說,輸入空格式規格會產生和對值呼叫 str() 函式相同的結果,非空的格式規格才會修改結果。

標準格式說明符號 (standard format specifier) 的一般型式如下:

format_spec     ::=  [[fill]align][sign]["z"]["#"]["0"][width][grouping_option]["." precision][type]
fill            ::=  <any character>
align           ::=  "<" | ">" | "=" | "^"
sign            ::=  "+" | "-" | " "
width           ::=  digit+
grouping_option ::=  "_" | ","
precision       ::=  digit+
type            ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

如果給定了一個有效的 align 值,則可以在它之前加一個 fill 字元,且該字元可為任意字元,若不加的話預設為空格。使用格式字串str.format() 時是無法在其中使用大括號("{" 或 "}")作為 fill 字元的,但仍可透過巢狀替換欄位的方式插入大括號。此限制不影響 format() 函式。

各种对齐选项的含义如下:

選項

含意

'<'

強制欄位在可用空間內靠左對齊(這是大多數物件的預設值)。

'>'

強制欄位在可用空間內靠右對齊(這是數字的預設值)。

'='

强制在符号(如果有)之后数码之前放置填充。 这被用于以 '+000000120' 形式打印字段。 这个对齐选项仅对数字类型有效。 这是当 '0' 紧接在字段宽度之前时的默认选项。

'^'

強制欄位在可用空間內置中。

請注意,除非有定義了最小欄位寬度,否則欄位寬度將始終與填充它的資料大小相同,故在該情況下的對齊選項是沒有意義的。

sign 選項只適用於數字型別,並可為以下之一:

選項

含意

'+'

表示正數與負數均需使用符號。

'-'

表示标志应仅用于负数(这是默认行为)。

space

表示正數應使用前導空格,負數應使用減號。

The 'z' option coerces negative zero floating-point values to positive zero after rounding to the format precision. This option is only valid for floating-point presentation types.

在 3.11 版的變更: 新增 'z' 選項(請見 PEP 682)。

'#' 选项可让“替代形式”被用于执行转换。 替代形式会针对不同的类型分别定义。 此选项仅适用于整数、浮点数和复数类型。 对于整数类型,当使用二进制、八进制或十六进制输出时,此选项会为输出值分别添加相应的 '0b', '0o', '0x''0X' 前缀。 对于浮点数和复数类型,替代形式会使得转换结果总是包含小数点符号,即使其不带小数部分。 通常只有在带有小数部分的情况下,此类转换的结果中才会出现小数点符号。 此外,对于 'g''G' 转换,末尾的零不会从结果中被移除。

',' 选项表示使用逗号作为千位分隔符。 对于感应区域设置的分隔符,请改用 'n' 整数表示类型。

在 3.1 版的變更: 新增 ',' 選項(請見 PEP 378)。

'_' 選項表示對於浮點表示型別和整數表示型別 'd' 使用底線作為千位分隔符號。對於整數表示型別 'b''o''x''X',每 4 位數字會插入底線。對於其他表示型別,指定此選項會出錯。

在 3.6 版的變更: 新增 '_' 選項(請見 PEP 515)。

width 是一個十進位整數,定義了最小總欄位寬度,包括任何前綴、分隔符號和其他格式字元。如果未指定,則欄位寬度將由內容決定。

當未給予明確的對齊指示,在 width 欄位前面填入零 ('0') 字元將會為數值型別啟用有符號察覺的零填充 (sign-aware zero-padding)。這相當於使用 '0'fill 字元且對齊類型為 '='

在 3.10 版的變更: width 欄位前面加上 '0' 不再影響字串的預設對齊方式。

precision 是一個十進位整數,指定表示類型 'f''F' 的小數點後應顯示多少位,或表示類型 'g''G' 的小數點前後應顯示多少位。對於字串表示類型,該欄位指定最大欄位大小 - 換言之,將使用欄位中的多少字元。整數表示類型不允許使用 precision

最終,型別決定了資料將會如何呈現

可用的字串表示型別有:

型別

含意

's'

字符串格式。这是字符串的默认类型,可以省略。

None

's' 一样。

可用的整数表示类型是:

型別

含意

'b'

二进制格式。 输出以 2 为基数的数字。

'c'

字符。在打印之前将整数转换为相应的unicode字符。

'd'

十进制整数。 输出以 10 为基数的数字。

'o'

八进制格式。 输出以 8 为基数的数字。

'x'

十六進位格式。輸出以 16 為基數的數字,9 以上的數字使用小寫字母。

'X'

十六進位格式。輸出以 16 為基數的數字,9 以上的數字使用大寫字母。如果指定了 '#',則前綴 '0x' 也會被轉成大寫的 '0X'

'n'

数字。 这与 'd' 相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。

None

'd' 相同。

在上述的表示类型之外,整数还可以通过下列的浮点表示类型来格式化 (除了 'n'None)。 当这样做时,会在格式化之前使用 float() 将整数转换为浮点数。

floatDecimal 值的可用表示类型有:

型別

含意

'e'

科学计数法。 对于一个给定的精度 p,将数字格式化为以字母 'e' 分隔系数和指数的科学计数法形式。 系数在小数点之前有一位,之后有 p 位,总计 p + 1 个有效数位。 如未指定精度,则会对 float 采用小数点之后 6 位精度,而对 Decimal 则显示所有系数位。 如果小数点之后没有数位,则小数点也会被略去,除非使用了 # 选项。

'E'

科学计数法。 与 'e' 相似,不同之处在于它使用大写字母 'E' 作为分隔字符。

'f'

定点表示法。 对于一个给定的精度 p,将数字格式化为在小数点之后恰好有 p 位的小数形式。 如未指定精度,则会对 float 采用小数点之后 6 位精度,而对 Decimal 则使用大到足够显示所有系数位的精度。 如果小数点之后没有数位,则小数点也会被略去,除非使用了 # 选项。

'F'

定点表示。 与 'f' 相似,但会将 nan 转为 NAN 并将 inf 转为 INF

'g'

常规格式。 对于给定精度 p >= 1,这会将数值舍入到 p 个有效数位,再将结果以定点表示法或科学计数法进行格式化,具体取决于其值的大小。 精度 0 会被视为等价于精度 1

准确的规则如下:假设使用表示类型 'e' 和精度 p-1 进行格式化的结果具有指数值 exp。 那么如果 m <= exp < p,其中 m 以 -4 表示浮点值而以 -6 表示 Decimal 值,该数字将使用类型 'f' 和精度 p-1-exp 进行格式化。 否则的话,该数字将使用表示类型 'e' 和精度 p-1 进行格式化。 在两种情况下,都会从有效数字中移除无意义的末尾零,如果小数点之后没有余下数字则小数点也会被移除,除非使用了 '#' 选项。

如未指定精度,会对 float 采用 6 个有效数位的精度。 对于 Decimal,结果的系数会沿用原值的系数数位;对于绝对值小于 1e-6 的值以及最小有效数位的位值大于 1 的数值将会使用科学计数法,在其他情况下则会使用定点表示法。

正负无穷,正负零和 nan 会分别被格式化为 inf, -inf, 0, -0nan,无论精度如何设定。

'G'

常规格式。 类似于 'g',不同之处在于当数值非常大时会切换为 'E'。 无穷与 NaN 也会表示为大写形式。

'n'

数字。 这与 'g' 相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。

'%'

百分比。 将数字乘以 100 并显示为定点 ('f') 格式,后面带一个百分号。

None

对于 float 来说这类似于 'g',不同之处在于当使用定点表示法时,小数点之后将至少显示一位。 所用的精度会大到足以精确表示给定的值。

对于 Decimal 来说这相当于 'g''G',具体取决于当前 decimal 上下文的 context.capitals 值。

总体效果是将 str() 的输出匹配为其他格式化因子所调整出的样子。

格式範例

本節包含 str.format() 語法以及與舊式 % 格式的比較。

此語法在大多情況下與舊式的 % 格式類似,只是增加了 {}: 來取代 %。例如,'%03.2f' 可以改寫為 '{:03.2f}'

新的語法還支援新的選項,將在以下的範例中說明。

按位置存取引數:

>>> '{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>> '{}, {}, {}'.format('a', 'b', 'c')  # 3.1+ only
'a, b, c'
>>> '{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>> '{2}, {1}, {0}'.format(*'abc')      # unpacking argument sequence
'c, b, a'
>>> '{0}{1}{0}'.format('abra', 'cad')   # arguments' indices can be repeated
'abracadabra'

按名稱存取引數:

>>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
'Coordinates: 37.24N, -115.81W'
>>> coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
>>> 'Coordinates: {latitude}, {longitude}'.format(**coord)
'Coordinates: 37.24N, -115.81W'

存取引數的屬性:

>>> c = 3-5j
>>> ('The complex number {0} is formed from the real part {0.real} '
...  'and the imaginary part {0.imag}.').format(c)
'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.'
>>> class Point:
...     def __init__(self, x, y):
...         self.x, self.y = x, y
...     def __str__(self):
...         return 'Point({self.x}, {self.y})'.format(self=self)
...
>>> str(Point(4, 2))
'Point(4, 2)'

存取引數的內容:

>>> coord = (3, 5)
>>> 'X: {0[0]};  Y: {0[1]}'.format(coord)
'X: 3;  Y: 5'

替換 %s%r

>>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
"repr() shows quotes: 'test1'; str() doesn't: test2"

對齊文字以及指定寬度:

>>> '{:<30}'.format('left aligned')
'left aligned                  '
>>> '{:>30}'.format('right aligned')
'                 right aligned'
>>> '{:^30}'.format('centered')
'           centered           '
>>> '{:*^30}'.format('centered')  # use '*' as a fill char
'***********centered***********'

替換 %+f%-f% f 以及指定正負號:

>>> '{:+f}; {:+f}'.format(3.14, -3.14)  # show it always
'+3.140000; -3.140000'
>>> '{: f}; {: f}'.format(3.14, -3.14)  # show a space for positive numbers
' 3.140000; -3.140000'
>>> '{:-f}; {:-f}'.format(3.14, -3.14)  # show only the minus -- same as '{:f}; {:f}'
'3.140000; -3.140000'

替換 %x%o 並將其值轉換為不同的進位制:

>>> # format also supports binary numbers
>>> "int: {0:d};  hex: {0:x};  oct: {0:o};  bin: {0:b}".format(42)
'int: 42;  hex: 2a;  oct: 52;  bin: 101010'
>>> # with 0x, 0o, or 0b as prefix:
>>> "int: {0:d};  hex: {0:#x};  oct: {0:#o};  bin: {0:#b}".format(42)
'int: 42;  hex: 0x2a;  oct: 0o52;  bin: 0b101010'

使用逗號作為千位分隔符:

>>> '{:,}'.format(1234567890)
'1,234,567,890'

表示為百分比:

>>> points = 19
>>> total = 22
>>> 'Correct answers: {:.2%}'.format(points/total)
'Correct answers: 86.36%'

作為特定型別格式:

>>> import datetime
>>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)
>>> '{:%Y-%m-%d %H:%M:%S}'.format(d)
'2010-07-04 12:15:58'

巢狀引數及更多複雜範例:

>>> for align, text in zip('<^>', ['left', 'center', 'right']):
...     '{0:{fill}{align}16}'.format(text, fill=align, align=align)
...
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
>>>
>>> octets = [192, 168, 0, 1]
>>> '{:02X}{:02X}{:02X}{:02X}'.format(*octets)
'C0A80001'
>>> int(_, 16)
3232235521
>>>
>>> width = 5
>>> for num in range(5,12): 
...     for base in 'dXob':
...         print('{0:{width}{base}}'.format(num, base=base, width=width), end=' ')
...     print()
...
    5     5     5   101
    6     6     6   110
    7     7     7   111
    8     8    10  1000
    9     9    11  1001
   10     A    12  1010
   11     B    13  1011

模板字串

模板字串提供如 PEP 292 所述更簡單的字串替換。模板字串的主要用例是國際化 (i18n),因為在這種情況下,更簡單的語法和功能使得它比其他 Python 內建字串格式化工具更容易翻譯。基於模板字串建構的 i18n 函式庫範例,請參閱 flufl.i18n 套件。

模板字符串支持基于 $ 的替换,使用以下规则:

  • $$ 为转义符号;它会被替换为单个的 $

  • $identifier 为替换占位符,它会匹配一个名为 "identifier" 的映射键。 在默认情况下,"identifier" 限制为任意 ASCII 字母数字(包括下划线)组成的字符串,不区分大小写,以下划线或 ASCII 字母开头。 在 $ 字符之后的第一个非标识符字符将表明占位符的终结。

  • ${identifier} 等价于 $identifier。 当占位符之后紧跟着有效的但又不是占位符一部分的标识符字符时需要使用,例如 "${noun}ification"

在字符串的其他位置出现 $ 将导致引发 ValueError

string 模块提供了实现这些规则的 Template 类。 Template 有下列方法:

class string.Template(template)

该构造器接受一个参数作为模板字符串。

substitute(mapping={}, /, **kwds)

進行模板替換,並回傳一個新的字串。 mapping 是任何有金鑰並符合模板裡佔位符號的字典型物件。或者如果關鍵字就是佔位符號時,你也可以改提供關鍵字引數。當 mappingkwds 同時給定並存在重複時,kwds 的佔位符號會被優先使用。

safe_substitute(mapping={}, /, **kwds)

類似於 substitute(),但如果 mappingkwds 中缺少佔位符號的話,原始的佔位符號會完整地出現在結果字串裡,而不會引發 KeyError 例外。此外,與 substitute() 不同的是,任何包含 $ 的字句會直接回傳 $ 而非引發 ValueError

雖然仍可能發生其他例外,但這個方法被認為是「安全」的,因為它總是試圖回傳一個有用的字串而不是引發例外。從另一個角度來看,safe_substitute() 可能並非完全安全,因為它會默默忽略格式錯誤的模板,這些模板包含了多餘的左右定界符、不匹配的括號,或者不是有效的 Python 識別字的佔位符號。

is_valid()

如果模板有將導致 substitute() 引發 ValueError 的無效佔位符號,就會回傳 false。

在 3.11 版新加入.

get_identifiers()

回傳模板中有效識別字的串列,按照它們首次出現的順序,並忽略任何無效的識別字。

在 3.11 版新加入.

Template 實例也提供一個公開的資料屬性:

template

這是傳遞給建構函式 template 引數的物件。一般來說,你不應該改變它,但並沒有強制設定成唯讀。

以下是如何使用 Template 的一個範例:

>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d)
Traceback (most recent call last):
...
ValueError: Invalid placeholder in string: line 1, col 11
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
...
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'

進階用法:你可以衍生 Template 類別來自定義佔位符號語法、左右定界符字元,或者用於剖析模板字串的正則表達式。你可以透過覆寫這些類別屬性來達成:

  • delimiter -- 這是描述引入左右定界符的文字字串。預設值是 $。請注意這不是正規表示式,因為實作會在需要時對這個字串呼叫 re.escape()。也請注意你不能在建立類別後修改左右定界符。(意即在子類別的命名空間中必須設置不同的左右定界符)

  • idpattern -- 这是用来描述不带花括号的占位符的模式的正则表达式。 默认值为正则表达式 (?a:[_a-z][_a-z0-9]*)。 如果给出了此属性并且 braceidpatternNone 则此模式也将作用于带花括号的占位符。

    備註

    由于默认的 flagsre.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 -- 此群組與任何其他左右定界符模式(通常是單一左右定界符)匹配,且它應該出現在正規表示式的最後。

當此模式有匹配於模板但這些命名組中卻有任一個不匹配,此類別的方法將引發 ValueError

輔助函式

string.capwords(s, sep=None)

使用 str.split() 將引數分割為字詞,使用 str.capitalize() 將每個單字大寫,並使用 str.join() 將大寫字詞連接起來。如果可選的第二引數 sep 不存在或為 None,則連續的空白字元將替換為單一空格,並且刪除前導和尾隨空白;在其他情況下則使用 sep 來分割和連接單字。