开始python 从入门到精通 Working with Strings(如何处理字符串)

    技术2025-07-20  13

    你们以前见过字符串,也知道如何制作它们。你还看到了如何访问他们的个人字符通过索引和切片。在本章中,您将看到如何使用它们来格式化其他值并快速了解使用字符串方法可以做的有用的事情,例如分裂,连接,搜索,和更多。

    Basic String Operations

           所有的标准序列操作(索引、切片、乘法、成员关系、长度、最小值、和最大)工作字符串,正如您在前一章看到的。记住,字符串是不可变,所以所有类型的项或片分配都是非法的。

    >>> website = 'http://www.python.org' >>> website[-3:] = 'com' Traceback (most recent call last): File "<pyshell#19>", line 1, in ? website[-3:] = 'com' TypeError: object doesn't support slice assignment  

    String Formatting: The Short Version

            将值格式化为字符串是一项非常重要的操作,而且必须满足各种不同的需求,因此多年来已经在该语言中添加了几种方法。过去,主要的解决方案是使用(名称恰当的)字符串格式化操作符百分号。这个操作符的行为模仿了C语言中的经典printf函数。在%的左边,放置一个字符串(格式字符串);在它的右边,放置您想要格式化的值。可以使用单个值,比如字符串或数字,也可以使用值的元组(如果希望格式化多个值),或者,正如我在下一章中讨论的,可以使用字典。最常见的情况是元组。

    >>> format = "Hello, %s. %s enough for ya?" >>> values = ('world', 'Hot') >>> format % values 'Hello, world. Hot enough for ya?'

    格式字符串的%s部分称为转换说明符。它们标记了要插入值的位置。s表示值应该被格式化为字符串;如果不是t,则使用str进行转换。例如,%。3f将该值格式化为具有三个小数的浮点数。这个格式化方法仍然有效,在很多代码中仍然很活跃,所以你可能会碰到它。您可能遇到的另一种解决方案是所谓的模板字符串,它是不久前出现的一种简化基本格式化机制的尝试,例如使用类似于UNIX shell的语法。

    >>> from string import Template >>> tmpl = Template("Hello, $who! $what enough for ya?") >>> tmpl.substitute(who="Mars", what="Dusty") 'Hello, Mars! Dusty enough for ya?'  

    带等号的参数就是所谓的关键字参数,你会在第六章中听到很多。在字符串格式化的上下文中,您可以将它们视为向指定替换字段提供值的一种方式。在编写新代码时,选择的机制是format string方法,它结合并扩展了以前方法的优点。每个替换字段都包含在花括号中,可能包括一个名称,以及关于如何转换和格式化为该字段提供的值的信息。最简单的情况是字段没有名称,或者每个名称只是一个索引。

    >>> "{}, {} and {}".format("first", "second", "third") 'first, second and third' >>> "{0}, {1} and {2}".format("first", "second", "third") 'first, second and third' 不过,指数不需要像这样排列

    >>> "{3} {0} {2} {1} {3} {0}".format("be", "not", "or", "to") 'to be or not to be 命名字段如预期的那样工作。

    >>> from math import pi >>> "{name} is approximately {value:.2f}.".format(value=pi, name="π") 'π is approximately 3.14.‘

    当然,关键字参数的顺序并不重要。在本例中,我还提供了一种格式 .2f的说明符,与字段名用冒号分隔,这意味着我们需要用三个浮点格式 小数。如果没有指定,结果如下:

    >>> "{name} is approximately {value}.".format(value=pi, name="π") 'π is approximately 3.141592653589793.' 最后,在Python 3.6中,如果变量的名称与 相应的替代字段。在这种情况下,你可以使用所谓的f字符串,用前缀f写。

    >>> from math import e >>> f"Euler's constant is roughly {e}." "Euler's constant is roughly 2.718281828459045."

    在这里,名为e的替换字段只是提取同名变量的值作为字符串 正在建设。这相当于下面,稍微显式的表达:

    >>> "Euler's constant is roughly {e}.".format(e=e) "Euler's constant is roughly 2.718281828459045."

     

    String Formatting: The Long Version

     

    Replacement Field Names

    在最简单的情况下,只需提供未命名的参数来格式化格式化字符串并使用未命名的字段。然后,字段和参数按照给出的顺序成对出现。还可以为参数提供名称,然后在替换字段中使用名称来请求这些特定的值。这两种策略可以自由混合使用。

    >>> "{foo} {} {bar} {}".format(1, 2, bar=4, foo=3) '3 1 4 2' 还可以使用未命名参数的索引无序地请求它们

    >>> "{foo} {1} {bar} {0}".format(1, 2, bar=4, foo=3) '3 2 4 1'  然而,混合手动和自动字段编号是不允许的,因为这可能很快就会真的实现让人困惑。但是您不必使用所提供的值本身—您可以访问它们的一部分,就像in一样普通的Python代码。这里有一个例子:

    >>> fullname = ["Alfred", "Smoketoomuch"] >>> "Mr {name[1]}".format(name=fullname) 'Mr Smoketoomuch' >>> import math >>> tmpl = "The {mod.__name__} module defines the value {mod.pi} for π" >>> tmpl.format(mod=math) 'The math module defines the value 3.141592653589793 for π‘ 如您所见,我们可以对方法、属性或变量同时使用索引和点表示法导入模块中的函数。(看似奇怪的剩余名称__变量包含给定模块的名称。)

    Basic Conversions

    一旦指定了字段应该包含的内容,就可以添加关于如何格式化它的说明。首先,你 可以提供转换标志。

    >>> print("{pi!s} {pi!r} {pi!a}".format(pi="π")) π 'π' '\u03c0’

    这三个标志(s、r和a)分别使用str、repr和ascii进行转换。str函数通常为值创建一个外观自然的字符串版本(在本例中,它对输入不做任何操作字符串);repr字符串尝试创建给定值的Python表示(在本例中是字符串文字),而ascii函数坚持创建只包含字符的表示法ASCII编码。这与Python 2中repr的工作方式类似。

            您还可以指定要转换的值的类型,或者您希望将其视为哪种类型的值。例如,您可以提供一个整数,但希望将其视为小数。这是通过使用格式规范中的f字符(用于定点)来实现的,也就是在冒号分隔符之后

    >>> "The number is {num}".format(num=42) 'The number is 42' >>> "The number is {num:f}".format(num=42) 'The number is 42.000000' 或者你更愿意把它格式化成二进制数字?

    >>> "The number is {num:b}".format(num=42) 'The number is 101010' 有几个这样的类型说明符。列表见表3-1。

    TypeMeaningb将整数格式化为二进制数字。c将整数解释为Unicode代码点。d将整数格式化为十进制数字。默认为整数。e在科学记数法中格式化十进制数,用e表示指数。E与e相同,但用e表示指数。f使用固定数目的小数格式化一个十进制数。F与f相同,但格式化特殊值(nan和inf)为大写。g自动选择固定和科学符号。默认为十进制数,除了默认版本至少有一个小数。G与g相同,但将指数指示符和特殊值大写。n与g相同,但插入与语言环境相关的数字分隔符。o将整数格式化为八进制数。s按原样格式化字符串。默认为字符串。x将整数格式化为使用小写字母的十六进制数字X和x一样,只是大写字母%将数字格式化为百分数(乘以100,用f格式化,后跟%)

     

    Width, Precision, and Thousands Separators

    当格式化浮点数(或其他更特殊的十进制数类型)时,默认值为是在小数点后显示六个数字,在所有情况下,默认是让格式化后的值恰好显示它所需的宽度,没有任何填充。这些违约可能并不完全是什么当然,您需要,并且您可以增加关于宽度和精度的详细信息的格式规范来满足你的喜好。

    宽度用整数表示,如下:

    >>> "{num:10}".format(num=3) '          3' >>> "{name:10}".format(name="Bob") 'Bob       ' 可以看到,数字和字符串的对齐方式不同。我们将在下一节中回到对齐问题。 精度也由整数指定,但是它前面有一个句点,暗指小数点。

    >>> "Pi day is {pi:.2f}".format(pi=pi) 'Pi day is 3.14' 在这里,我显式地指定了f类型,因为默认值对精度的处理略有不同。(见 Python库引用的精确规则。)当然,你可以结合宽度和精度。

    >>> "{pi:10.2f}".format(pi=pi) '        3.14' 实际上,您也可以将precision用于其他类型,尽管您可能不经常需要它。

    >>> "{:.5}".format("Guido van Rossum") 'Guido' 最后,可以通过使用逗号表示需要数以千计的分隔符。

    >>> 'One googol is {:,}'.format(10**100) 'One googol is 10,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000,000,000,000,000,000,000,000,000,000,000,000,000' 当与其他格式化元素一起使用时,这个逗号应该位于宽度之间和周期指示精度。

     

    Signs, Alignment, and Zero-Padding (符号、对齐和补零)

    有相当一部分格式化机制是针对数字进行格式化的,例如,用于打印一个由对齐良好的值组成的表。宽度和精度可以让我们大致达到这个目的,但如果包含负数,我们漂亮的输出可能仍然会出错。正如你们看到的,字符串和数字的对齐方式不同;也许我们想要改变它,例如,在一列数字中间包含一段文本?在宽度和精度数字之前,可以放置一个标志,可以是零、加号、减号或空白。零表示该数字将被填充为零。

    >>> '{:010.2f}'.format(pi) '0000003.14 分别使用<、>和^来指定左对齐、右对齐和居中对齐。

    >>> print('{0:<10.2f}\n{0:^10.2f}\n{0:>10.2f}'.format(pi)) 3.14      3.14           3.14 您可以使用填充字符来增强对齐说明符,填充字符用于替代空格字符

    >>> "{:$^15}".format(" WIN BIG ") '$$$ WIN BIG $$$ 还有更专门的specifier =,它将任何填充字符放在符号和数字之间。

    >>> print('{0:10.2f}\n{1:10.2f}'.format(pi, -pi)) 3.14 -3.14 >>> print('{0:10.2f}\n{1:=10.2f}'.format(pi, -pi)) 3.14 - 3.14  

    如果还希望包含正数的符号,可以使用说明符+(在对齐之后)指定符(如果有),而不是默认的-。如果你使用空格字符,正号将有一个空格插入而不是a +。

    >>> print('{0:-.2}\n{1:-.2}'.format(pi, -pi)) # Default 3.1 -3.1

     

    >>> print('{0:+.2}\n{1:+.2}'.format(pi, -pi)) +3.1 -3.1 >>> print('{0: .2}\n{1: .2}'.format(pi, -pi)) 3.1 -3.1 最后一个组件是hash(#)选项,将其放在符号和宽度之间(如果是的话)礼物)。这触发了另一种形式的转换,不同类型之间的细节不同。例如,对于二进制、八进制和十六进制转换,要添加一个前缀。

    >>> "{:b}".format(42) '101010' >>> "{:#b}".format(42) '0b101010

    对于各种类型的小数,它强制包含小数点(对于g,它保持小数0)。

    >>> "{:g}".format(42) '42' >>> "{:#g}".format(42) '42.0000'  

     

    String Methods

     

    center

    center方法通过在字符串的两边填充给定的填充字符-空格by来居中

    >>> "The Middle by Jimmy Eat World".center(39) ' The Middle by Jimmy Eat World ' >>> "The Middle by Jimmy Eat World".center(39, "*") '*****The Middle by Jimmy Eat World*****' In Appendix B: ljust, rjust, zfill.  

    find

    find方法在较大字符串中查找子字符串。它返回子字符串所在的最左边的索引发现。如果没有找到,则返回-1。

    >>> 'With a moo-moo here, and a moo-moo there'.find('moo') 7 >>> title = "Monty Python's Flying Circus" >>> title.find('Monty') 0 >>> title.find('Python') 6 >>> title.find('Flying') 15 >>> title.find('Zirquss') -1 还可以为搜索提供一个起点,也可以提供一个终点。

    >>> subject = '$$$ Get rich now!!! $$$' >>> subject.find('$$$') 0 >>> subject.find('$$$', 1) # Only supplying the start 20 >>> subject.find('!!!') 16 >>> subject.find('!!!', 0, 16) # Supplying start and end -1 注意,开始和停止值(第二个和第三个参数)指定的范围包括第一个索引,但不是第二个。这是Python中的常见做法。

     

    join

    是一个非常重要的字符串方法,join是split的逆。它用于连接序列中的元素。

    >>> seq = [1, 2, 3, 4, 5] >>> sep = '+' >>> sep.join(seq) # Trying to join a list of numbers Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: sequence item 0: expected string, int found >>> seq = ['1', '2', '3', '4', '5'] >>> sep.join(seq) # Joining a list of strings '1+2+3+4+5' >>> dirs = '', 'usr', 'bin', 'env' >>> '/'.join(dirs) '/usr/bin/env' >>> print('C:' + '\\'.join(dirs)) C:\usr\bin\env

    可以看到,要连接的序列元素都必须是字符串。注意后面两个中的方法我使用一个目录列表,并根据UNIX和DOS/的约定对它们进行格式化通过使用不同的分隔符(并在DOS版本中添加驱动器名称)。

     

    lower lower方法返回字符串的小写版本。

    >>> 'Trondheim Hammer Dance'.lower() 'trondheim hammer dance  

    replace

    replace方法返回一个字符串,其中一个字符串的所有匹配项都被另一个字符串替换。

    >>> 'This is a test'.replace('is', 'eez') 'Theez eez a test  

    split

    一个非常重要的字符串方法,它与join相反,用于将字符串分割为序列。

    >>> '1+2+3+4+5'.split('+') ['1', '2', '3', '4', '5'] >>> '/usr/bin/env'.split('/') ['', 'usr', 'bin', 'env'] >>> 'Using the default'.split() ['Using', 'the', 'default']  

    strip

    strip方法返回一个字符串,其中左边和右边(但内部没有)有空格

    >>> '         internal whitespace is kept          '.strip() 'internal whitespace is kept' 还可以通过在字符串参数中列出所有字符来指定要删除的字符

    >>> '*** SPAM * for * everyone!!! ***'.strip(' *!') 'SPAM * for * everyone'  

    translate

    但是,在使用translate之前,必须创建一个翻译表。此转换表包含关于应该将哪些Unicode代码点转换为哪些的信息。您可以在字符串类型str本身上使用maketrans方法构造这样一个表。该方法有两个参数:两个长度相等的字符串,其中第一个字符串中的每个字符应该替换为第二个字符串中相同位置的字符。3在我们的简单示例中,代码如下所示

    >>> table = str.maketrans('cs', 'kz') 如果愿意,我们可以查看表内部,不过我们将看到的是Unicode代码点之间的映射

    >>> table {115: 122, 99: 107}

    一旦有了翻译表,就可以将其用作翻译方法的参数。

    >>> 'this is an incredible test'.translate(table) 'thiz iz an inkredible tezt  

    第三个可选参数可以提供给maketrans,指定应该删除的字母。如果你例如,如果想要模仿说得非常快的德语,可以删除所有空格。

    >>> table = str.maketrans('cs', 'kz', ' ') >>> 'this is an incredible test'.translate(table) 'thizizaninkredibletezt  

     

    参考Beginning Python From Novice to Professional, 3rd Edition 第三章

    Processed: 0.014, SQL: 9