Skip to main content

6.1. string —常用字符串操作

源代码: Lib/string.py


6.1.1. 字符串常量

在此模块中定义的常量为:

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字符的字符串。这包括字符空格,制表符,换行符,返回,换页和垂直选项卡。

6.1.2. 自定义字符串格式

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

class string.Formatter

Formatter 类具有以下公共方法:

format(format_string, *args, **kwargs)

主要API方法。它需要一个格式字符串和一组任意位置和关键字参数。它只是一个调用 vformat() 的包装器。

3.5 版后已移除: 传递格式字符串作为关键字参数 format_string 已被弃用。

vformat(format_string, args, kwargs)

此函数执行格式化的实际工作。它暴露为一个单独的函数,用于想要传递参数的预定义字典,而不是使用 *args**kwargs 语法将字典解包和重新打包为单个参数。 vformat() 执行将格式字符串拆分为字符数据和替换字段的工作。它调用下面描述的各种方法。

此外,Formatter 定义了许多旨在被子类替换的方法:

parse(format_string)

循环format_string并返回元组的可迭代(literal_textfield_nameformat_specconversion)。这被 vformat() 用来将字符串拆分为文本文本或替换字段。

元组中的值在概念上表示文本文本的跨度,后跟单个替换字段。如果没有文本文本(如果两个替换字段连续出现,就会发生),那么 literal_text 将是一个零长度字符串。如果没有替换字段,则 field_nameformat_specconversion 的值将是 None

get_field(field_name, args, kwargs)

给定 parse() 返回的 field_name (见上文),将其转换为要格式化的对象。返回一个元组(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”将导致使用 key 参数0调用 get_value()。通过调用内置的 getattr() 函数,在 get_value() 返回后将查找 name 属性。

如果索引或关键字指向不存在的项目,则应该引发 IndexErrorKeyError

check_unused_args(used_args, args, kwargs)

如果需要,实现检查未使用的参数。此函数的参数是在格式字符串(位置参数的整数和命名参数的字符串)中实际引用的所有参数键的集合,以及对传递给vformat的 argskwargs 的引用。可以从这些参数计算未使用的args的集合。如果检查失败,则假定 check_unused_args() 引发异常。

format_field(value, format_spec)

format_field() 只是调用内置的全局 format()。提供该方法,以便子类可以覆盖它。

convert_field(value, conversion)

给定转换类型(如 parse() 方法返回的元组),转换由 get_field() 返回的值。默认版本理解为’‘(str),’r’(repr)和’a’(ascii)转换类型。

6.1.3. 格式字符串语法

str.format() 方法和 Formatter 类共享格式字符串的相同语法(虽然在 Formatter 的情况下,子类可以定义自己的格式字符串语法)。语法与 格式化的字符串文字 的语法相关,但有差异。

格式字符串包含由大括号 {} 包围的“替换字段”。大括号中不包含的任何内容都被视为文字文本,它不会被复制到输出。如果您需要在文本文本中包含大括号字符,可以通过加倍转义:{{}}

替换字段的语法如下:

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
arg_name          ::=  [identifier | integer]
attribute_name    ::=  identifier
element_index     ::=  integer | index_string
index_string      ::=  <any source character except "]"> +
conversion        ::=  "r" | "s" | "a"
format_spec       ::=  <described in the next section>

在较不正式的术语中,替换字段可以从 field_name 开始,该 field_name 指定其值将被格式化并插入输出而不是替换字段的对象。 field_name 任选地后面是 conversion 字段,其前面是感叹号 '!',和 format_spec,其前面是结肠 ':'。这些指定替换值的非默认格式。

另见 格式规范Mini-Language 部分。

field_name 本身以 arg_name 开头,arg_name 是数字或关键字。如果它是一个数字,它指的是一个位置参数,如果它是一个关键字,它指的是一个命名的关键字参数。如果格式字符串中的数字arg_names按顺序为0,1,2,...,则它们都可以省略(不仅仅是一些),并且数字0,1,2,...将按照该顺序自动插入。因为 arg_name 不是引号分隔的,所以不可能在格式字符串中指定任意字典键(例如,字符串 '10'':-]')。 arg_name 后面可以跟随任意数量的索引或属性表达式。表单 '.name' 的表达式使用 getattr() 选择命名属性,而表单 '[index]' 的表达式使用 __getitem__() 进行索引查找。

在 3.1 版更改: 可以省略位置参数说明符,因此 '{} {}' 等同于 '{0} {1}'

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

"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 字符串之前被替换。这允许动态指定值的格式。

有关示例,请参阅 格式示例 部分。

6.1.3.1. 格式规范Mini-Language

“格式规范”用于格式字符串中包含的替换字段中,以定义如何显示各个值(请参阅 格式字符串语法格式化字符串文字)。它们也可以直接传递到内置的 format() 函数。每个格式表类型可以定义如何解释格式规范。

大多数内置类型实现格式规范的以下选项,尽管某些格式化选项仅受数字类型支持。

一个常规约定是,空格式字符串("")产生相同的结果,如果你调用 str() 的值。非空格式字符串通常会修改结果。

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

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

如果指定了有效的 align 值,则可以在其前面有一个 fill 字符,该字符可以是任何字符,如果省略,则默认为空格。不能使用字面大括号(“ { ”或“ } ”)作为 格式化字符串文字 中的 fill 字符或使用 str.format() 方法时。但是,可以插入带有嵌套替换字段的大括号。此限制不会影响 format() 功能。

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

选项

含义

'<'

强制该字段在可用空间内左对齐(这是大多数对象的默认值)。

'>'

强制字段在可用空间内右对齐(这是数字的默认值)。

'='

强制将填充放置在符号(如果有)之后但在数字之前。这用于以“+000000120”形式打印字段。此对齐选项仅对数字类型有效。当‘0’紧接在字段宽度之前时,它变为默认值。

'^'

强制字段在可用空间中居中。

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

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

选项

含义

'+'

表示正号和负号都应使用符号。

'-'

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

空间

表示在正数上使用前导空格,在负数上使用负号。

'#' 选项使“备用表单”用于转换。不同类型的替代形式定义不同。此选项仅对整数,浮点,复数和十进制类型有效。对于整数,当使用二进制,八进制或十六进制输出时,此选项将相应的前缀 '0b''0o''0x' 添加到输出值。对于浮点数,复数和小数,替换形式导致转换的结果始终包含小数点字符,即使后面没有数字。通常,只有在数字跟随它后,这些转换的结果才会出现小数点字符。此外,对于 'g''G' 转换,不从结果中删除尾随零。

',' 选项用信号通知使用逗号作为千位分隔符。对于区域设置感知分隔符,请改用 'n' 整数呈现类型。

在 3.1 版更改: 添加了 ',' 选项(另见 PEP 378)。

'_' 选项向浮点表示类型和整数表示类型 'd' 的千位分隔符使用下划线。对于整数呈现类型 'b''o''x''X',每4个数字插入下划线。对于其他表示类型,指定此选项是一个错误。

在 3.6 版更改: 添加了 '_' 选项(另见 PEP 515)。

width 是定义最小字段宽度的十进制整数。如果未指定,则字段宽度将由内容确定。

当没有给出显式对齐时,通过零('0')字符在 width 字段之前允许数字类型的符号感知零填充。这相当于 alignment 类型为 '=''0'fill 字符。

precision 是一个十进制数,指示对于使用 'f''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() 用于在格式化之前将整数转换为浮点数。

可用的浮点和十进制值的表示类型有:

类型

含义

'e'

指数符号。以科学记数法打印数字,使用字母“e”表示指数。默认精度为 6

'E'

指数符号。与 'e' 相同,除了它使用大写字母“E”作为分隔符。

'f'

固定点。以定点编号显示编号。默认精度为 6

'F'

固定点。与 'f' 相同,但将 nan 转换为 NAN,将 inf 转换为 INF

'g'

一般格式。对于给定精度 p >= 1,将数字四舍五入到 p 有效数字,然后根据其大小以固定点格式或科学记数法格式化结果。

准确的规则如下:假设格式化为呈现类型 'e' 和精确 p-1 的结果将具有指数 exp。然后如果 -4 <= exp < p,数字格式化为呈现类型 'f' 和精确 p-1-exp。否则,该数字被格式化为呈现类型 'e' 和精确 p-1。在这两种情况下,从有效位数中删除无效的尾部零,如果没有剩余的数字,小数点也被删除。

无论精度如何,正负无穷大,正负零,和nans分别格式化为 inf-inf0-0nan

0 的精度被视为等同于 1 的精度。默认精度为 6

'G'

一般格式。与 'g' 相同,除非切换到 'E',如果数字太大。无穷大和NaN的表示也是大写的。

'n'

数。这与 'g' 相同,除了它使用当前语言环境设置插入适当的数字分隔符字符。

'%'

百分比。将数字乘以100并以固定('f')格式显示,后跟百分比符号。

None

'g' 类似,除了定点符号使用时,至少有一个数字超过小数点。默认精度是表示特定值所需的精度。总体效果是匹配由其他格式修饰符改变的 str() 的输出。

6.1.3.2. 格式示例

本节包含 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

6.1.4. 模板字符串

模板提供了简单的字符串替换,如 PEP 292 中所述。代替正常的基于 % 的替换,模板使用以下规则支持基于 $ 的替换:

  • $$ 是一种逃避;它被替换为单个 $

  • $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标识符的占位符的畸形模板。

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 - 这是描述占位符引入分隔符的文字字符串。默认值为 $。注意,这应该是 not 是正则表达式,因为实现将根据需要在这个字符串上调用 re.escape()

  • idpattern - 这是描述非支撑占位符模式的正则表达式(大括号将根据需要自动添加)。默认值为正则表达式 [_a-z][_a-z0-9]*

  • flags - 在编译用于识别替换的正则表达式时应用的正则表达式标志。默认值为 re.IGNORECASE。注意,re.VERBOSE 将总是添加到标志,因此自定义 idpattern 必须遵循verbose正则表达式的约定。

    3.2 新版功能.

或者,您可以通过覆盖类属性 pattern 来提供整个正则表达式模式。如果执行此操作,该值必须是具有四个命名捕获组的正则表达式对象。捕获组对应于上面给出的规则,以及无效的占位符规则:

  • escaped - 此组匹配转义序列,例如。 $$,在默认模式。

  • named - 此组与未支持的占位符名称匹配;它不应该在捕获组中包括分隔符。

  • braced - 此组与括号括起的占位符名称匹配;它不应该在捕获组中包括分隔符或大括号。

  • invalid - 此组匹配任何其他分隔符模式(通常为单个分隔符),它应该出现在正则表达式的最后。

6.1.5. 帮助函数

string.capwords(s, sep=None)

使用 str.split() 将参数分成单词,使用 str.capitalize() 将每个单词大写,并使用 str.join() 连接大写的单词。如果可选的第二个参数 sep 不存在或 None,则空格字符的运行被单个空格替换,前导和尾部空格被删除,否则 sep 用于拆分和连接字。