Python 1-10 字符串操作

1、字符串拼接

>>> s = 'hello'*2                                       
>>> s = 'hello'+'world'  
>>> s = 'hello' 'world'
                                 
>>> s = "This is a Python program."
>>> lst = s.split() # 分割字符串为列表
>>> lst
['This', 'is', 'a', 'Python', 'program.']
>>> s = ' '.join(lst) # 连接列表为字符串
>>> s
'This is a Python program.'

2、字符串提取

>>> s = 'abcdef12345'
>>> s[3:7]
'def1'
>>> s[1:7:2]
'bdf'
>>> s[4:]
'ef12345'
>>> s[:4]
'abcd'
>>> s[:]
'abcdef12345'
>>> s[::-1]
'54321fedcba'

3、字符串切割

>>> s = 'I love you more than I can say'
>>> s.split()
['I', 'love', 'you', 'more', 'than', 'I', 'can', 'say']
>>> s.split('o')
['I l', 've y', 'u m', 're than I can say']
>>> s.split(' ',3)
['I', 'love', 'you', 'more than I can say']
>>> s = '''江畔何人初见月
...         江月何年初照人
...         人生代代无穷已
...         江月年年望相似'''
>>> s.splitlines() # split('\n')
['江畔何人初见月', '        江月何年初照人', '        人生代代无穷已', '        江月年年望相似
']
>>> s.splitlines(True)
['江畔何人初见月\n', '        江月何年初照人\n', '        人生代代无穷已\n', '        江月年年
望相似']
>>> s.splitlines(False)
['江畔何人初见月', '        江月何年初照人', '        人生代代无穷已', '        江月年年望相似
']
>>> [x.strip() for x in s.splitlines()] # 列表推导式 
['江畔何人初见月', '江月何年初照人', '人生代代无穷已', '江月年年望相似']

4、字符串删除

>>> s = ' \t ---abc123+++ \n   '
>>> s.strip()
'---abc123+++'
>>> s.strip().strip('-+')
'abc123'
>>> s[6:12]
'abc123'
>>> s.replace(' ','') # 删除 空格
'\t---abc123+++\n'

5、字符串替换

str.replace(old, new[, max])
返回字符串中的 old 替换成 new 后生成的新字符串,替换不超过 max 次。

str = "this is string example....wow!!! this is really string"
print(str.replace("is", "was"))
print(str.replace("is", "was", 3))

练习

doc = '''

a happy day 

Last Sunday,I visited my grandmother.

We listened to music and planted flowers.

I counted the flowers.There were ten..

Then I helped my grandmother cook lunch.

When we finished,I washed the dishes and she cleaned the kitchen.

In the evening,I watched TV and played the violin at home,It was fun.

'''

练习 以下是参考代码,每一行后面要求添加详细注释。
1、去除空行

# 方法一
a = doc.splitlines() # 每一行后面添加详细注释
# b=[]
# for l in a:
#     if l: # if l != ''
#         b.append(l)
b = [x for x in a if x] # 列表推导式
c = '\n'.join(b)
print(c)
# 方法二 只考虑了一行空行
c = doc.replace('\n\n','\n')
print(c)

2、第一行标题化

x = c.split('\n', 1)
x[0] = x[0].title()
m = '\n'.join(x)
print(m)

3、统计单词数 每个单词出现的次数

# 保留字母、数字和换行符(\n),去除其它符号。
# 方法一
z = ''
for c in m:
    if c.isalnum() or c == '\n':
        z += c    # z = z + c
    else:
        z += ' '
# 方法二
# 使用列表推导式 [条件表达式 for x in s if 条件二 ] 条件表达式:x if 条件一 else y
# 条件一 是 x 有两种情况选择 条件二 是只筛选满足条件的,限定筛选的条件。
y = [o if o.isalpha() else ' ' for o in m ]
z = ''.join(y) 

n = z.split()
print(n)

s = set(n) # set() 把 列表转换成集合 可以去重 
d = {} # {} 空字典 {'is':3,}
for i in s:
    d[i] = n.count(i)
print(len(d))
print(d)

4、单词表随机排列

k = list(s)
import random
random.shuffle(k) # 原地随机排序
print(k)
k.sort() # 原地排序 升序
print(k)

附 string — 常见的字符串操作

1、字符串常量

>>> import string
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.hexdigits
'0123456789abcdefABCDEF'
>>> string.octdigits
'01234567'
>>> string.punctuation # 标点符号的 ASCII 字符所组成的字符串
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>> string.printable # 可打印符号的 ASCII 字符组成的字符串
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> string.whitespace # 空白符号的 ASCII 字符组成的字符串。
' \t\n\r\x0b\x0c'

2、自定义字符串格式化

内置的字符串类提供了通过使用 PEP 3101 所描述的 format() 方法进行复杂变量替换和值格式化的能力。 string 模块中的 Formatter 类允许你使用与内置 format() 方法相同的实现来创建并定制你自己的字符串格式化行为。

格式字符串包含有以花括号 {} 括起来的“替换字段”。 不在花括号之内的内容被视为字面文本,会不加修改地复制到输出中。 如果你需要在字面文本中包含花括号字符,可以通过重复来转义: {{ 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       ::=  <described in the next section>

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

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

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

"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 字段包含值应如何呈现的规格描述,例如字段宽度、对齐、填充、小数精度等细节信息。 每种值类型可以定义自己的“格式化迷你语言”或对 format_spec 的解读方式。

大多数内置类型都支持同样的格式化迷你语言,具体描述见下一节。

format_spec 字段还可以在其内部包含嵌套的替换字段。 这些嵌套的替换字段可能包括字段名称、转换旗标和格式规格描述,但是不再允许更深层的嵌套。 format_spec 内部的替换字段会在解读 format_spec 字符串之前先被解读。 这将允许动态地指定特定值的格式。

请参阅 格式示例 一节查看相关示例。

格式规格迷你语言

“格式规格”在格式字符串所包含的替换字段内部使用,用于定义单个值应如何呈现 (参见 格式字符串语法 和 格式字符串字面值)。 它们也可以被直接传给内置的 format() 函数。 每种可格式化的类型都可以自行定义如何对格式规格进行解读。

大多数内置类型都为格式规格实现了下列选项,不过某些格式化选项只被数值类型所支持。

一般约定空的格式描述将产生与在值上调用 str() 相同的结果。 非空格式描述通常会修改此结果。

标准格式说明符 的一般形式如下:

format_spec     ::=  [[fill]align][sign][#][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() 方法时是无法使用花括号字面值 (“{” or “}”) 作为 fill 字符的。 但是,通过嵌套替换字段插入花括号则是可以的。 这个限制不会影响 format() 函数。

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

'<' 强制字段在可用空间内左对齐(这是大多数对象的默认值)。
'>' 强制字段在可用空间内右对齐(这是数字的默认值)。
'=' 强制将填充放置在符号(如果有)之后但在数字之前。这用于以“+000000120”形式打印字段。此对齐选项仅对数字类型有效。当'0'紧接在字段宽度之前时,它成为默认值。
'^' 强制字段在可用空间内居中。

请注意,除非定义了最小字段宽度,否则字段宽度将始终与填充它的数据大小相同,因此在这种情况下,对齐选项没有意义。

sign 选项仅对数字类型有效,可以是以下之一:

'+' 表示标志应该用于正数和负数。
'-' 表示标志应仅用于负数(这是默认行为)。
space 表示应在正数上使用前导空格,在负数上使用减号。

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

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

width 是一个定义最小总字段宽度的十进制整数,包括任何前缀、分隔符和其他格式化字符。 如果未指定,则字段宽度将由内容确定。

当未显式给出对齐方式时,在 width 字段前加一个零 (‘0’) 字段将为数字类型启用感知正负号的零填充。 这相当于设置 fill 字符为 ‘0’ 且 alignment 类型为 ‘=’。

precision 是一个十进制数字,表示对于以 ‘f’ and ‘F’ 格式化的浮点数值要在小数点后显示多少个数位,或者对于以 ‘g’ 或 ‘G’ 格式化的浮点数值要在小数点前后共显示多少个数位。 对于非数字类型,该字段表示最大字段大小 —— 换句话说就是要使用多少个来自字段内容的字符。 对于整数值则不允许使用 precision。

最后,type 确定了数据应如何呈现。

可用的字符串表示类型是:

's' 字符串格式。这是字符串的默认类型,可以省略。
None 和 's' 一样。

可用的整数表示类型是:

'b' 二进制格式。 输出以 2 为基数的数字。
'c' 字符。在打印之前将整数转换为相应的unicode字符。
'd' 十进制整数。 输出以 10 为基数的数字。
'o' 八进制格式。 输出以 8 为基数的数字。
'x' 十六进制格式。 输出以 16 为基数的数字,使用小写字母表示 9 以上的数码。
'X' 十六进制格式。 输出以 16 为基数的数字,使用大写字母表示 9 以上的数码。
'n' 数字。 这与 'd' 相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。
None 和 'd' 相同。

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

float 和 Decimal 值的可用表示类型有:

'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, -0 和 nan,无论精度如何设定。

'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} 等价于 Python 1-10 字符串操作_python{noun}ification"。

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

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

class string.Template(template)
该构造器接受一个参数作为模板字符串。

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

执行模板替换,返回一个新字符串。 mapping 为任意字典类对象,其中的键将匹配模板中的占位符。 或者你也可以提供一组关键字参数,其中的关键字即对应占位符。 当同时给出 mapping 和 kwds 并且存在重复时,则以 kwds 中的占位符为优先。

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

类似于 substitute(),不同之处是如果有占位符未在 mapping 和 kwds 中找到,不是引发 KeyError 异常,而是将原始占位符不加修改地显示在结果字符串中。 另一个与 substitute() 的差异是任何在其他情况下出现的 $ 将简单地返回 $ 而不是引发 ValueError。

此方法被认为“安全”,因为虽然仍有可能发生其他异常,但它总是尝试返回可用的字符串而不是引发一个异常。 从另一方面来说,safe_substitute() 也可能根本算不上安全,因为它将静默地忽略错误格式的模板,例如包含多余的分隔符、不成对的花括号或不是合法 Python 标识符的占位符等等。

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]*)。 如果给出了此属性并且 braceidpattern 为 None 则此模式也将作用于带花括号的占位符。

注解 由于默认的 flags 为 re.IGNORECASE,模式 [a-z] 可以匹配某些非 ASCII 字符。 因此我们在这里使用了局部旗标 a。

辅助函数

string.capwords(s, sep=None)

使用 str.split() 将参数拆分为单词,使用 str.capitalize() 将单词转为大写形式,使用 str.join() 将大写的单词进行拼接。 如果可选的第二个参数 sep 被省略或为 None,则连续的空白字符会被替换为单个空格符并且开头和末尾的空白字符会被移除,否则 sep 会被用来拆分和拼接单词。