如何在 Python 中反转字符串?

2024-11-20 08:43:00
admin
原创
8
摘要:问题描述:reversePython 的对象没有内置方法str。如何反转字符串?解决方案 1:使用切片:>>> 'hello world'[::-1] 'dlrow olleh' 切片符号采用 的形式[start:stop:step]。在本例中,我们省略了start和stop位置,因为我们想...

问题描述:

reversePython 的对象没有内置方法str。如何反转字符串?


解决方案 1:

使用切片:

>>> 'hello world'[::-1]
'dlrow olleh'

切片符号采用 的形式[start:stop:step]。在本例中,我们省略了startstop位置,因为我们想要整个字符串。我们还使用step = -1,这意味着“从右向左反复移动 1 个字符”。

解决方案 2:

实现字符串反向函数的最佳方法是什么?

我自己对这个问题的经验是学术性的。但是,如果你是一个寻求快速答案的专业人士,请使用以下步骤-1

>>> 'a string'[::-1]
'gnirts a'

或者更易读(但由于方法名称查找和 join 在给定迭代器时形成列表的事实,速度较慢)str.join,:

>>> ''.join(reversed('a string'))
'gnirts a'

或者为了提高可读性和可重用性,将切片放在函数中

def reversed_string(a_string):
    return a_string[::-1]

进而:

>>> reversed_string('a_string')
'gnirts_a'

详细解释

如果您对学术论述感兴趣,请继续阅读。

Python 的 str 对象中没有内置的反向函数。

以下是关于 Python 字符串你应该知道的几件事:

  1. 在 Python 中,字符串是不可变的。更改字符串并不会修改该字符串。它会创建一个新的字符串。

  2. 字符串是可切片的。切片字符串会以给定的增量从字符串中的一个点向后或向前到另一个点生成一个新的字符串。它们采用切片符号或下标中的切片对象:

string[subscript]

下标通过在括号内包含冒号来创建切片:

    string[start:stop:step]

要在括号外创建切片,您需要创建一个切片对象:

    slice_obj = slice(start, stop, step)
    string[slice_obj]

一种可读的方法:

虽然''.join(reversed('foo'))可读性强,但它需要在另一个被调用函数上调用字符串方法str.join,这可能相对较慢。让我们把它放在一个函数中——我们稍后再讨论它:

def reverse_string_readable_answer(string):
    return ''.join(reversed(string))

最高效的方法:

使用反向切片会更快:

'foo'[::-1]

但是,对于不太熟悉切片或原作者意图的人来说,我们如何才能使其更具可读性和可理解性呢?让我们在下标符号之外创建一个切片对象,给它一个描述性的名称,并将其传递给下标符号。

start = stop = None
step = -1
reverse_slice = slice(start, stop, step)
'foo'[reverse_slice]

作为函数实现

为了真正将其实现为一个函数,我认为只需使用一个描述性名称在语义上就足够清楚了:

def reversed_string(a_string):
    return a_string[::-1]

使用方法很简单:

reversed_string('foo')

你的老师可能想要的是:

如果您有一位导师,他们可能希望您从一个空字符串开始,然后从旧字符串构建一个新字符串。您可以使用 while 循环通过纯语法和文字来执行此操作:

def reverse_a_string_slowly(a_string):
    new_string = ''
    index = len(a_string)
    while index:
        index -= 1                    # index = index - 1
        new_string += a_string[index] # new_string = new_string + character
    return new_string

从理论上讲,这是不好的,因为请记住,字符串是不可变的- 因此每次当你在 上添加一个字符时new_string,理论上每次都会创建一个新的字符串!但是,CPython 知道如何在某些情况下优化这一点,这个简单的例子就是其中之一。

最佳实践

理论上更好的方法是将子字符串收集到一个列表中,然后稍后再将它们加入:

def reverse_a_string_more_slowly(a_string):
    new_strings = []
    index = len(a_string)
    while index:
        index -= 1                       
        new_strings.append(a_string[index])
    return ''.join(new_strings)

但是,正如我们将在下面的 CPython 时间中看到的,这实际上需要更长的时间,因为 CPython 可以优化字符串连接。

时间安排

具体时间如下:

>>> a_string = 'amanaplanacanalpanama' * 10
>>> min(timeit.repeat(lambda: reverse_string_readable_answer(a_string)))
10.38789987564087
>>> min(timeit.repeat(lambda: reversed_string(a_string)))
0.6622700691223145
>>> min(timeit.repeat(lambda: reverse_a_string_slowly(a_string)))
25.756799936294556
>>> min(timeit.repeat(lambda: reverse_a_string_more_slowly(a_string)))
38.73570013046265

CPython 优化了字符串连接,而其他实现可能不会:

... 对于 a += b 或 a = a + b 形式的语句,不要依赖 CPython 就地字符串连接的有效实现。这种优化即使在 CPython 中也很脆弱(它只适用于某些类型),并且在未使用引用计数的实现中根本不存在。在库的性能敏感部分,应改用 ''.join() 形式。这将确保连接在各种实现中以线性时间发生。

解决方案 3:

@Paolo 的s[::-1]方法最快;较慢的方法(可能更具可读性,但这是有争议的)是''.join(reversed(s))

解决方案 4:

这个答案有点长,包含 3 个部分:现有解决方案的基准为什么这里的大多数解决方案是错误的我的解决方案

现有的答案只有在忽略 Unicode 修饰符/字素簇的情况下才是正确的。我稍后会处理这个问题,但首先看一下一些反转算法的速度:

在此处输入图片描述

注意:我所说的list_comprehension应该称为slicing

slicing         : min:   0.6μs, mean:   0.6μs, max:    2.2μs
reverse_func    : min:   1.9μs, mean:   2.0μs, max:    7.9μs
reverse_reduce  : min:   5.7μs, mean:   5.9μs, max:   10.2μs
reverse_loop    : min:   3.0μs, mean:   3.1μs, max:    6.8μs

在此处输入图片描述

slicing         : min:   4.2μs, mean:   4.5μs, max:   31.7μs
reverse_func    : min:  75.4μs, mean:  76.6μs, max:  109.5μs
reverse_reduce  : min: 749.2μs, mean: 882.4μs, max: 2310.4μs
reverse_loop    : min: 469.7μs, mean: 577.2μs, max: 1227.6μs

您可以看到,切片(reversed = string[::-1])的时间在所有情况下都是最短的(即使在修复我的拼写错误之后)。

字符串反转

如果你真的想以常识性的方式反转一个字符串,那么它要复杂得多。例如,以下面的字符串为例(棕色手指指向左边,黄色手指指向上面)。这是两个字素,但有 3 个 unicode 码点。额外的一个是皮肤修饰符。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用