写点什么

Python 中的反转字符串:reversed()、切片等

  • 2021 年 11 月 17 日
  • 本文字数:6697 字

    阅读完需:约 22 分钟

​​摘要:以相反的顺序反转和处理字符串可能是编程中的一项常见任务。Python 提供了一组工具和技术,可以帮助您快速有效地执行字符串反转。

 

本文分享自华为云社区《Python 中的反转字符串:reversed()、切片等》,作者: Yuchuan 。

 

当您经常在代码中使用 Python 字符串时,您可能需要以相反的顺序使用它们。Python 包含一些方便的工具和技术,可以在这些情况下为您提供帮助。使用它们,您将能够快速有效地构建现有字符串的反向副本。


了解这些在 Python 中反转字符串的工具和技术将帮助您提高作为 Python 开发人员的熟练程度。


在本教程中,您将学习如何:

  • 通过切片快速构建反向字符串

  • 使用和创建现有字符串的反向副本 reversed().join()

  • 使用迭代递归手动反转现有字符串

  • 对字符串执行反向迭代

  • 使用相反的顺序对字符串进行排序 sorted()


为了最大限度地利用本教程,你应该知道的基本知识串,for 以及 while 循环和递归。

使用核心 Python 工具反转字符串


在某些特定情况下,可能需要以相反的顺序使用 Python 字符串。例如,假设您有一个字符串,并且想要一种快速的方法来反转它以获取. 您可以使用哪些 Python 工具来提供帮助?"ABCDEF""FEDCBA"


字符串在 Python 中是不可变的,因此不可能原地反转给定的字符串。您需要创建目标字符串的反向副本以满足要求。


Python 提供了两种直接的方法来反转字符串。由于字符串是序列,因此它们是 indexablesliceable iterable。这些功能允许您使用切片以相反的顺序直接生成给定字符串的副本。第二个选项是使用内置函数 reversed()创建一个迭代器,该迭代器以相反的顺序生成输入字符串的字符。

通过切片反转字符串


切片是一种有用的技术,它允许您使用称为 offsets 的整数索引的不同组合从给定序列中提取项目。当涉及到切片字符串时,这些偏移量定义了切片中第一个字符的索引、停止切片的字符的索引,以及一个定义每次迭代要跳过多少个字符的值。


要对字符串进行切片,可以使用以下语法:


a_string[start:stop:step]
复制代码


​你的偏移量 start,stop 和 step。此表达式从 startto stop −1by 中提取所有字符 step。稍后您将更深入地了解这一切意味着什么。


所有偏移量都是可选的,它们具有以下默认值:



​这里,start 表示切片中第一个字符 stop 的索引,同时保存停止切片操作的索引。第三个偏移量 step 允许您决定切片在每次迭代中将跳过多少个字符。


注意:切片操作在达到等于或大于 的索引时完成 stop。这意味着它永远不会在最终切片中包含该索引处的项目(如果有)。


该 step 偏移允许您微调如何,而跳过其他从字符串中提取所需的字符:

>>> 


>>> letters = "AaBbCcDd"
>>> # Get all characters relying on default offsets>>> letters[::]'AaBbCcDd'>>> letters[:]'AaBbCcDd'
>>> # Get every other character from 0 to the end>>> letters[::2]'ABCD'
>>> # Get every other character from 1 to the end>>> letters[1::2]'abcd'
复制代码


​在这里,您首先在 letters 不提供显式偏移值的情况下进行切片以获取原始字符串的完整副本。为此,您还可以使用省略第二个冒号 ( :)的切片。随着 step 等于 2,切片会从目标字符串中的每个其它字符。您可以使用不同的偏移量来更好地了解切片的工作原理。


为什么切片和第三个偏移量与 Python 中的字符串反转有关?答案在于如何 step 处理负值。如果为 提供负值 step,则切片向后运行,即从右到左。


例如,如果您设置为 stepequal -1,那么您可以构建一个以相反顺序检索所有字符的切片:

>>> 


>>> letters = "ABCDEF"
>>> letters[::-1]'FEDCBA'
>>> letters'ABCDEF'
复制代码


​此切片返回从字符串右端(索引等于)到 len(letters) - 1 字符串左端(索引为 )的所有字符 0。当您使用此技巧时,您会以相反的顺序获得原始字符串的副本,而不会影响 的原始内容 letters。


创建现有字符串的反向副本的另一种技术是使用 slice(). 这个内置函数的签名如下:


slice(start, stop, step)
复制代码


​此函数接受三个参数,与切片运算符中的偏移量具有相同的含义,并返回一个切片对象,表示调用

range(start,stop, step).


您可以使用 slice()来模拟切片[::-1]并快速反转字符串。继续并 slice()在方括号内运行以下调用:

>>> 


>>> letters = "ABCDEF"
>>> letters[slice(None, None, -1)]'FEDCBA'
复制代码


​传递 None 给 的前两个参数 slice()告诉函数您要依赖其内部默认行为,这与没有 start 和值的标准切片相同 stop。换句话说,传递 None 给 start 和 stop 意味着您需要从底层序列的左端到右端的切片。

使用.join()和反转字符串


reversed()第二种,可以说是最 Pythonic 的反转字符串的方法是 reversed()与 str.join(). 如果您将字符串传递给 reversed(),您将获得一个以相反顺序生成字符的迭代器:

>>> 


>>> greeting = reversed("Hello, World!")
>>> next(greeting)'!'>>> next(greeting)'d'>>> next(greeting)'l'
复制代码


​当您将 next()withgreeting 作为参数调用时,您会从原始字符串的右端获取每个字符。


需要注意的重要一点 reversed()是,生成的迭代器直接从原始字符串中生成字符。换句话说,它不会创建一个新的反向字符串,而是从现有字符串反向读取字符。这种行为在内存消耗方面相当有效,并且在某些上下文和情况下(例如迭代)可能是一个根本性的胜利。


您可以使用 reversed()直接调用获得的迭代器作为参数.join():

>>> 


>>> "".join(reversed("Hello, World!"))'!dlroW ,olleH'
复制代码


​在这个单行表达式中,您将调用的结果 reversed()直接作为参数传递给.join()。因此,您将获得原始输入字符串的反向副本。的组合 reversed(),并.join()为扭转字符串一个很好的选择。

手动生成反转字符串


到目前为止,您已经了解了快速反转字符串的核心 Python 工具和技术。大多数时候,它们将是您的最佳选择。但是,您可能需要在编码冒险的某个时刻手动反转字符串。


在本节中,您将学习如何使用显式循环和递归来反转字符串。最后一种技术在 Pythonreduce()函数的帮助下使用函数式编程方法。

反转循环中的字符串


您将用于反转字符串的第一种技术涉及 for 循环和连接运算符 ( +)。使用两个字符串作为操作数,此运算符返回一个连接原始字符串的新字符串。整个操作称为串联


注意:使用.join()是在 Python 中连接字符串的推荐方法。它干净、高效且 Pythonic。


这是一个函数,它接受一个字符串并使用串联在循环中反转它:

>>> 


>>> def reversed_string(text):...     result = ""...     for char in text:...         result = char + result...     return result...
>>> reversed_string("Hello, World!")'!dlroW ,olleH'
复制代码


​在每次迭代中,循环采用后续字符 char, fromtext 并将其与 的当前内容连接起来 result。请注意,result 最初保存的是一个空字符串 ( "")。然后将新的中间字符串重新分配给 result。在循环结束时,result 保存一个新字符串作为原始字符串的反向副本。


注意:由于 Python 字符串是不可变的数据类型,您应该记住本节中的示例使用了一种浪费技术。它们依赖于创建连续的中间字符串,只是为了在下一次迭代中将它们丢弃。


如果您更喜欢使用 whileloop,那么您可以执行以下操作来构建给定字符串的反向副本:

>>> 


>>> def reversed_string(text):...     result = ""...     index = len(text) - 1...     while index >= 0:...         result += text[index]...         index -= 1...     return result...
>>> reversed_string("Hello, World!")'!dlroW ,olleH'
复制代码


​在这里,您首先使用 计算 index 输入字符串中最后一个字符的 len()。循环从 index 下到并包括 0。在每次迭代中,您都使用扩充赋值运算符 ( +=) 创建一个中间字符串,该字符串将的内容 result 与来自 的相应字符连接起来 text。同样,最终结果是通过反转输入字符串产生的新字符串。

用递归反转字符串


您还可以使用递归来反转字符串。递归是指函数在自己的主体中调用自身。为了防止无限递归,您应该提供一个无需再次调用函数即可生成结果的基本情况。第二个组件是递归 case,它启动递归循环并执行大部分计算。


下面是如何定义一个递归函数,该函数返回给定字符串的反向副本:

>>> 


>>> def reversed_string(text):...     if len(text) == 1:...         return text...     return reversed_string(text[1:]) + text[:1]...
>>> reversed_string("Hello, World!")'!dlroW ,olleH'
复制代码


​在本例中,您首先检查基本情况。如果输入字符串只有一个字符,则将该字符串返回给调用者。


最后一个语句,即递归情况,调用 reversed_string()自身。该调用使用 text[1:]输入字符串的切片作为参数。此切片包含 中的所有字符 text,第一个除外。下一步是将递归调用的结果与 text[:1]包含 的第一个字符的单字符串 相加 text。


在上面的例子中需要注意的一个重要问题是,如果你将一个长字符串作为参数传递给 reversed_string(),那么你将得到一个 RecursionError:

>>> 


>>> very_long_greeting = "Hello, World!" * 1_000
>>> reversed_string(very_long_greeting)Traceback (most recent call last): ...RecursionError: maximum recursion depth exceeded while calling a Python object
复制代码


​达到 Python 的默认递归限制是您应该在代码中考虑的一个重要问题。但是,如果您确实需要使用递归,那么您仍然可以选择手动设置递归限制。


您可以通过调用 getrecursionlimit()from 来检查当前 Python 解释器的递归限制 sys。默认情况下,此值通常为 1000。您可以使用 setrecursionlimit()来自同一模块的 sys. 使用这些函数,您可以配置 Python 环境,以便您的递归解决方案可以工作。来试试看吧!

使用 reduce()扭转字符串


如果您更喜欢使用函数式编程方法,则可以使用 reduce()fromfunctools 来反转字符串。Pythonreduce()将折叠或归约函数和可迭代对象作为参数。然后它将提供的函数应用于输入迭代中的项目并返回单个累积值。


以下是您可以如何利用 reduce()反转字符串的方法:

>>> 


>>> from functools import reduce
>>> def reversed_string(text):... return reduce(lambda a, b: b + a, text)...
>>> reversed_string("Hello, World!")'!dlroW ,olleH'
复制代码


​在此示例中,该 lambda 函数采用两个字符串并以相反的顺序连接它们。调用在循环中 reduce()应用 lambdatotext 并构建原始字符串的反向副本。

反向遍历字符串


有时您可能希望以相反的顺序遍历现有字符串,这种技术通常称为反向迭代。根据您的特定需求,您可以使用以下选项之一对字符串进行反向迭代:

  • 该 reversed()内置功能

  • 切片运算符, [::-1]

反向迭代可以说是这些工具最常见的用例,因此在以下几节中,您将了解如何在迭代上下文中使用它们。

该 reversed()内置功能


以相反顺序迭代字符串的最可读和 Pythonic 的方法是使用 reversed(). 不久前,当您将它与.join()创建反向字符串一起使用时,您已经了解了该函数。


但是,主要意图和用例 reversed()是支持 Python 可迭代对象的反向迭代。以字符串作为参数,reversed()返回一个迭代器,该迭代器以相反的顺序从输入字符串中产生字符。


以下是如何以相反的顺序迭代字符串 reversed():

>>> 


>>> greeting = "Hello, World!"
>>> for char in reversed(greeting):... print(char)...!dlroW
,olleH
>>> reversed(greeting)<reversed object at 0x7f17aa89e070>
复制代码


​for 此示例中的循环非常具有可读性。的名称 reversed()清楚地表达了其意图并传达了该函数不会对输入数据产生任何副作用。由于 reversed()返回一个迭代器,循环在内存使用方面也很有效。

切片运算符, [::-1]


对字符串执行反向迭代的第二种方法是使用您之前在 a_string[::-1]示例中看到的扩展切片语法。即使这种方法不利于内存效率和可读性,它仍然提供了一种快速迭代现有字符串的反向副本的方法:

>>> 


>>> greeting = "Hello, World!"
>>> for char in greeting[::-1]:... print(char)...!dlroW
,olleH
>>> greeting[::-1]'!dlroW ,olleH'
复制代码


​在本例中,您应用切片运算符 greeting 来创建它的反向副本。然后你使用那​​个新的反向字符串来馈送循环。在这种情况下,您正在迭代一个新的反向字符串,因此该解决方案的内存效率低于使用 reversed().

创建自定义可逆字符串


如果您曾经尝试过反转 Python 列表,那么您就会知道列表有一个方便的方法,称为原位.reverse()反转底层列表。由于字符串在 Python 中是不可变的,因此它们不提供类似的方法。


但是,您仍然可以使用.reverse()模仿 list.reverse(). 您可以这样做:

>>> 


>>> from collections import UserString
>>> class ReversibleString(UserString):... def reverse(self):... self.data = self.data[::-1]...
复制代码


​ReversibleString 继承自 UserString,它是 collections 模块的一个类。UserString 是 str 内置数据类型的包装器。它是专门为创建 str. UserString 当您需要创建具有附加功能的自定义字符串类时非常方便。UserString 提供与常规字符串相同的功能。它还添加了一个称为.data 持有的公共属性,并允许您访问包装的字符串对象。


在里面 ReversibleString,你创造.reverse()。此方法反转包装的字符串.data 并将结果重新分配回.data. 从外部看,调用的.reverse()工作就像将字符串反转到位。然而,它实际上做的是创建一个新的字符串,以相反的顺序包含原始数据。


以下是 ReversibleString 实践中的工作原理:

>>> 


>>> text = ReversibleString("Hello, World!")>>> text'Hello, World!'
>>> # Reverse the string in place>>> text.reverse()>>> text'!dlroW ,olleH'
复制代码


​当您调用.reverse()on 时 text,该方法就像您正在对底层字符串进行就地更改一样。但是,您实际上是在创建一个新字符串并将其分配回包装的字符串。请注意,text 现在以相反的顺序保存原始字符串。


由于 UserString 提供与其超类相同的功能 str,因此您可以 reversed()开箱即用地执行反向迭代:

>>> 


>>> text = ReversibleString("Hello, World!")
>>> # Support reverse iteration out of the box>>> for char in reversed(text):... print(char)...!dlroW
,olleH
>>> text"Hello, World!"
复制代码


​在这里,您调用 reversed()withtext 作为参数来提供 for 循环。此调用按预期工作并返回相应的迭代器,因为 UserString 从 str. 请注意,调用 reversed()不会影响原始字符串。

以相反的顺序对 Python 字符串进行排序


您将学习的最后一个主题是如何以相反的顺序对字符串的字符进行排序。当您不按特定顺序处理字符串并且需要按逆字母顺序对它们进行排序时,这会很方便。


要解决此问题,您可以使用 sorted(). 这个内置函数返回一个列表,其中包含输入可迭代的所有项目。除了输入可迭代之外,sorted()还接受 reverse 关键字参数。True 如果您希望输入可迭代对象按降序排序,则可以将此参数设置为:

>>> 


>>> vowels = "eauoi"
>>> # Sort in ascending order>>> sorted(vowels)['a', 'e', 'i', 'o', 'u']
>>> # Sort in descending order>>> sorted(vowels, reverse=True)['u', 'o', 'i', 'e', 'a']
复制代码


​当您 sorted()使用字符串作为参数调用并 reverse 设置为 True 时,您会得到一个包含输入字符串字符的倒序或降序列表。由于 sorted()返回一个 list 对象,您需要一种方法将该列表转换回字符串。同样,您可以.join()像在前面的部分中一样使用:

>>> 

>>> vowels = "eauoi"
>>> "".join(sorted(vowels, reverse=True))'uoiea'
复制代码


​在此代码片段中,您调用.join()了一个空字符串,它扮演着分隔符的角色。参数 to.join()是调用 sorted()withvowels 作为参数并 reverse 设置为 True 的结果。


您还可以利用 sorted()以排序和反向顺序遍历字符串:

>>> 

>>> for vowel in sorted(vowels, reverse=True):...     print(vowel)......uoiea
复制代码


​该 reverse 给的说法 sorted()可以让你排序 iterables,包括字符串,按降序排列。因此,如果您需要按逆字母顺序排序的字符串字符,那么 sorted()适合您。

结论


相反的顺序反转和处理字符串可能是编程中的一项常见任务。Python 提供了一组工具和技术,可以帮助您快速有效地执行字符串反转。在本教程中,您了解了这些工具和技术以及如何在字符串处理挑战中利用它们。


在本教程中,您学习了如何:

  • 通过切片快速构建反向字符串

  • 使用 reversed()和创建现有字符串的反向副本.join()

  • 使用迭代递归手动创建反向字符串

  • 以相反的顺序循环遍历字符串

  • 使用降序对字符串进行排序 sorted()


尽管本主题本身可能没有很多令人兴奋的用例,但了解如何反转字符串对于入门级职位的编码面试很有用。您还会发现掌握反转字符串的不同方法可以帮助您真正概念化 Python 中字符串的不变性,这是该语言的一个显着特性。


点击关注,第一时间了解华为云新鲜技术~

发布于: 17 分钟前阅读数: 2
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
Python 中的反转字符串:reversed()、切片等