本文分享自华为云社区《在 Python 中拆分、连接和连接字符串》,作者: Yuchuan 。
生活中几乎没有什么保证:死亡、税收和需要处理字符串的程序员。字符串可以有多种形式。它们可以是非结构化文本、用户名、产品描述、数据库列名称,或者我们使用语言描述的任何其他内容。
由于字符串数据几乎无处不在,因此掌握有关字符串的交易工具非常重要。幸运的是,Python 使字符串操作变得非常简单,尤其是与其他语言甚至旧版本的 Python 相比时。
在本文中,您将学习一些最基本的字符串操作:拆分、连接和连接。您不仅会学习如何使用这些工具,而且会更深入地了解它们的工作原理。

  拆分字符串

在 Python 中,字符串表示为str对象,它们是不可变的:这意味着不能直接更改内存中表示的对象。这两个事实可以帮助您学习(然后记住)如何使用.split().
您是否已经猜到字符串的这两个特性与 Python 中的拆分功能有何关系?如果您猜测这.split()是一个实例方法,因为字符串是一种特殊类型,那么您是对的!在其他一些语言(如 Perl)中,原始字符串用作独立.split()函数的输入,而不是对字符串本身调用的方法。
注意:调用字符串方法的方法
像这样的字符串方法.split()在这里主要显示为在字符串上调用的实例方法。它们也可以被称为静态方法,但这并不理想,因为它更“冗长”。为了完整起见,这里有一个例子:
  
  1. # Avoid this:
  2. str.split('a,b,c', ',')

当您将其与首选用法进行比较时,这既笨重又笨拙:
  
  1. # Do this instead:
  2. 'a,b,c'.split(',')

有关 Python 中的实例、类和静态方法的更多信息,请查看我们的深入教程。
字符串不变性怎么样?这应该提醒您字符串方法不是就地操作,但它们会在内存中返回一个新对象。
注意:就地操作
就地操作是直接更改调用它们的对象的操作。一个常见的例子是在列表上使用的.append()方法:当你调用一个列表时,通过将输入添加到同一个列表来直接更改该列表。.append().append()
  无参数拆分
在深入之前,让我们看一个简单的例子:
  
  1. >>>
  2. >>> 'this is my string'.split()
  3. ['this', 'is', 'my', 'string']

这实际上是.split()调用的一个特例,我选择它是为了它的简单性。没有指定任何分隔符,.split()将任何空格都算作分隔符。
裸调用的另一个特点.split()是它会自动删除前导和尾随空格,以及连续的空格。比较.split()在没有分隔符参数的情况下调用以下字符串和有' '作为分隔符参数的调用:
  
  1. >>>
  2. >>> s = ' this   is  my string '
  3. >>> s.split()
  4. ['this', 'is', 'my', 'string']
  5. >>> s.split(' ')
  6. ['', 'this', '', '', 'is', '', 'my', 'string', '']

首先要注意的是,这展示了 Python 中字符串的不变性:后续调用.split()处理原始字符串,而不是第一次调用.split().
您应该看到的第二件事也是主要的事情是,bare .split()call 提取句子中的单词并丢弃任何空格。

  指定分隔符
.split(' '),另一方面,更字面意思。当有前导或尾随分隔符时,您将得到一个空字符串,您可以在结果列表的第一个和最后一个元素中看到该字符串。
如果有多个连续的分隔符(例如“this”和“is”之间以及“is”和“my”之间),第一个将用作分隔符,随后的分隔符将进入您的结果列表作为空字符串。

注意:调用中的分隔符 .split()

虽然上面的示例使用单个空格字符作为 的分隔符输入.split(),但用作分隔符的字符类型或字符串长度不受限制。唯一的要求是你的分隔符是一个字符串。你可以使用从"..."到 even 的任何东西"separator"。

  使用 Maxsplit 限制拆分
.split()有另一个可选参数称为maxsplit. 默认情况下,.split()将在调用时进行所有可能的拆分。maxsplit但是,当您为 赋值时,只会进行给定数量的拆分。使用我们之前的示例字符串,我们可以看到maxsplit:
  
  1. >>>
  2. >>> s = "this is my string"
  3. >>> s.split(maxsplit=1)
  4. ['this', 'is my string']

如上所示,如果设置maxsplit为1,则第一个空白区域将用作分隔符,其余的将被忽略。让我们做一些练习来测试到目前为止我们学到的一切。
练习:“自己尝试:Maxsplit”显示隐藏
当你给一个负数作为maxsplit参数时会发生什么?
解决方案:“自己尝试:Maxsplit”显示隐藏
.split()将在所有可用的分隔符上拆分您的字符串,这也是maxsplit未设置时的默认行为。
练习:“部分理解检查”显示隐藏
您最近收到了一个格式非常糟糕的逗号分隔值 (CSV) 文件。您的工作是将每一行提取到一个列表中,该列表的每个元素代表该文件的列。是什么让它格式错误?“地址”字段包含多个逗号,但需要在列表中表示为单个元素!
假设您的文件已作为以下多行字符串加载到内存中:
  
  1. Name,Phone,Address
  2. Mike Smith,15554218841,123 Nice St, Roy, NM, USA
  3. Anita Hernandez,15557789941,425 Sunny St, New York, NY, USA
  4. Guido van Rossum,315558730,Science Park 123, 1098 XG Amsterdam, NL

您的输出应该是一个列表列表:
  
  1. [
  2.     ['Mike Smith', '15554218841', '123 Nice St, Roy, NM, USA'],
  3.     ['Anita Hernandez', '15557789941', '425 Sunny St, New York, NY, USA'],
  4.     ['Guido van Rossum', '315558730', 'Science Park 123, 1098 XG Amsterdam, NL']
  5. ]

每个内部列表代表我们感兴趣的 CSV 行,而外部列表将它们保存在一起。
解决方案:“部分理解检查”显示隐藏
这是我的解决方案。有几种方法可以攻击它。重要的是您使用.split()了它的所有可选参数并获得了预期的输出:
  
  1. input_string = """Name,Phone,Address
  2. Mike Smith,15554218841,123 Nice St, Roy, NM, USA
  3. Anita Hernandez,15557789941,425 Sunny St, New York, NY, USA
  4. Guido van Rossum,315558730,Science Park 123, 1098 XG Amsterdam, NL"""
  5. def string_split_ex(unsplit):
  6.     results = []
  7.     # Bonus points for using splitlines() here instead,
  8.     # which will be more readable
  9.     for line in unsplit.split('\n')[1:]:
  10.         results.append(line.split(',', maxsplit=2))
  11.     return results
  12. print(string_split_ex(input_string))

我们.split()在这里打了两次电话。第一次使用可能看起来很吓人,但别担心!我们将逐步完成它,您会对这些表达式感到满意。让我们再看看第一个.split()调用:unsplit.split('\n')[1:].
第一个元素是unsplit,它只是指向输入字符串的变量。然后我们有我们的.split()电话:.split('\n')。在这里,我们正在拆分一个称为换行符的特殊字符
有什么作用\n?顾名思义,它告诉正在读取字符串的任何人,它后面的每个字符都应该显示在下一行。在像我们这样的多行字符串中,每行末尾input_string都有一个隐藏\n。
最后一部分可能是新的:[1:]. 到目前为止的语句给了我们一个内存中的新列表,[1:]看起来像一个列表索引符号,它是——有点!这个扩展的索引符号给了我们一个列表 slice。在这种情况下,我们取 index 处的元素1及其后的所有元素,丢弃 index 处的元素0。
总之,我们遍历一个字符串列表,其中每个元素代表多行输入字符串中除了第一行之外的每一行。
在每个字符串中,我们.split()再次调用using,作为拆分字符,但这次我们只使用maxsplit前两个逗号进行拆分,而地址保持不变。然后我们将该调用的结果附加到恰当命名的results数组并将其返回给调用者。

  连接和连接字符串
另一个基本的字符串操作与拆分字符串相反:字符串连接。如果你没见过这个词,别担心。这只是说“粘合在一起”的一种奇特方式。

  与+运算符连接
有几种方法可以做到这一点,具体取决于您要实现的目标。最简单和最常用的方法是使用加号 ( +) 将多个字符串相加。只需将 a 放在+您想要连接在一起的任意数量的字符串之间:
  
  1. >>>
  2. >>> 'a' + 'b' + 'c'
  3. 'abc'

为了与数学主题保持一致,您还可以将字符串相乘以重复它:
  
  1. >>>
  2. >>> 'do' * 2
  3. 'dodo'

请记住,字符串是不可变的!如果连接或重复存储在变量中的字符串,则必须将新字符串分配给另一个变量以保留它。
  
  1. >>>
  2. >>> orig_string = 'Hello'
  3. >>> orig_string + ', world'
  4. 'Hello, world'
  5. >>> orig_string
  6. 'Hello'
  7. >>> full_sentence = orig_string + ', world'
  8. >>> full_sentence
  9. 'Hello, world'

如果我们没有不可变的字符串,full_sentence则会输出'Hello, world, world'.
另一个注意事项是 Python 不进行隐式字符串转换。如果您尝试将字符串与非字符串类型连接起来,Python将引发一个TypeError:
  
  1. >>>
  2. >>> 'Hello' + 2
  3. Traceback (most recent call last):
  4.   File "<stdin>", line 1, in <module>
  5. TypeError: must be str, not int

这是因为您只能将字符串与其他字符串连接起来,如果您来自像 JavaScript 这样试图进行隐式类型转换的语言,这对您来说可能是一种新行为。

  在 Python 中从列表到字符串 .join()
还有另一种更强大的方法可以将字符串连接在一起。您可以使用该join()方法从 Python 中的列表转换为字符串。
这里的常见用例是当您有一个由字符串组成的可迭代对象(如列表),并且您希望将这些字符串组合成一个字符串时。就像.split(),.join()是一个字符串实例方法。如果您所有的字符串都在一个可迭代对象中,您会调用哪一个.join()?
这是一个有点棘手的问题。请记住,当您使用 时.split(),您将在要拆分的字符串或字符上调用它。相反的操作是.join(),因此您可以在要用于将可迭代字符串连接在一起的字符串或字符上调用它:
  
  1. >>>
  2. >>> strings = ['do', 're', 'mi']
  3. >>> ','.join(strings)
  4. 'do,re,mi'

在这里,我们strings用逗号 ( ,)连接列表的每个元素,并调用.join()它而不是strings列表。
练习:“通过加入提高可读性”显示隐藏
如何使输出文本更具可读性?
解决方案:“通过加入提高可读性”显示隐藏
您可以做的一件事是添加间距:
  
  1. >>>
  2. >>> strings = ['do', 're', 'mi']
  3. >>> ', '.join(strings)
  4. 'do, re, mi'

通过在我们的连接字符串中添加一个空格,我们大大提高了输出的可读性。在加入字符串以提高可读性时,您应该始终牢记这一点。
.join()很聪明,因为它将您的“joiner”插入到您想要加入的可迭代的字符串之间,而不是仅仅在可迭代的每个字符串的末尾添加您的joiner。这意味着,如果您传递 size 的迭代1,您将看不到您的加入者:
  
  1. >>>
  2. >>> 'b'.join(['a'])
  3. 'a'

练习:“部分理解检查”显示隐藏
使用我们的网页抓取教程,您已经构建了一个很棒的天气抓取工具。但是,它会在列表列表中加载字符串信息,每个列表都包含要写出到 CSV 文件的唯一信息行:
  
  1. [
  2.     ['Boston', 'MA', '76F', '65% Precip', '0.15 in'],
  3.     ['San Francisco', 'CA', '62F', '20% Precip', '0.00 in'],
  4.     ['Washington', 'DC', '82F', '80% Precip', '0.19 in'],
  5.     ['Miami', 'FL', '79F', '50% Precip', '0.70 in']
  6. ]

您的输出应该是如下所示的单个字符串:
  
  1. """
  2. Boston,MA,76F,65% Precip,0.15in
  3. San Francisco,CA,62F,20% Precip,0.00 in
  4. Washington,DC,82F,80% Precip,0.19 in
  5. Miami,FL,79F,50% Precip,0.70 in
  6. """

解决方案:“部分理解检查”显示隐藏
对于此解决方案,我使用了列表推导式,这是 Python 的一项强大功能,可让您快速构建列表。如果您想了解更多关于它们的信息,请查看这篇涵盖 Python 中所有可用推导式的精彩文章。
以下是我的解决方案,以列表列表开始并以单个字符串结尾:
  
  1. input_list = [
  2.     ['Boston', 'MA', '76F', '65% Precip', '0.15 in'],
  3.     ['San Francisco', 'CA', '62F', '20% Precip', '0.00 in'],
  4.     ['Washington', 'DC', '82F', '80% Precip', '0.19 in'],
  5.     ['Miami', 'FL', '79F', '50% Precip', '0.70 in']
  6. ]
  7. # We start with joining each inner list into a single string
  8. joined = [','.join(row) for row in input_list]
  9. # Now we transform the list of strings into a single string
  10. output = '\n'.join(joined)
  11. print(output)

这里我们.join()不是用一次,而是用了两次。首先,我们在列表推导中使用它,它将每个内部列表中的所有字符串组合成一个字符串。接下来,我们将每个字符串与\n我们之前看到的换行符连接起来。最后,我们简单地打印结果,以便我们可以验证它是否符合我们的预期。

  把这一切捆绑在一起
尽管 Python 中最基本的字符串操作(拆分、连接和连接)的概述到此结束,但仍有大量字符串方法可以让您更轻松地操作字符串。
一旦掌握了这些基本的字符串操作,您可能想了解更多。