在Python 3中,哪种方法更适合字符串反转?

7
s="google"
print("".join(reversed(s)))  //elgoog
print(s[::-1])  //elgoog

在上面的代码中,使用了Python 3中的reversed方法和切片方法来反转字符串,它们都显示相同的输出。但在Python编程语言中,哪种方法更有效呢?为什么?

这里是有关Python字符串翻转的比较链接 - Brad Solomon
5
可能是 Python 中字符串反转的重复问题 - Chris_Rands
1
建议的重复目标包括此答案中的相关基准 https://dev59.com/XXNA5IYBdhLWcg3wgeOk#27843760 - Chris_Rands
“最有效率” - 关于什么?速度?可读性?空间?你的使用情况是什么?反转效率在那里是否相关? - MisterMiyagi
2个回答

6
当谈到效率时,需要具体指出从哪个角度来考虑,如内存、运行时间、实现等等。
就运行时间而言,逆序索引肯定更快,因为当你使用join加上reversed时,你调用了两个函数,它们都有自己的缺点(挂起和恢复函数的框架等),相比之下,简单的索引更优。但是如果你想逐个字符地循环遍历字符串,无论出于什么目的,且内存是一个问题(主要是当字符串很大时),你可以使用reversed,因为它返回一个迭代器对象。
In [2]: s = "example"

In [4]: r = reversed(s)

In [5]: next(r)  # e.g. You can access to the characters using `next()`
Out[5]: 'e'

因此,结论是您应该根据自己的需求选择方法,这也是为什么Python中针对特定任务有多种方法的原因。

2
@jpp 我相信wim的评论适用于str.join调用之后。 - Chris_Rands
2
@jpp “reversed” 不会复制字符串,它会反向迭代。从来没有进行过复制。相比之下,“s[::1]”确实会创建一个副本。这就是为什么使用情况对于决定什么最有效是至关重要的原因。 - MisterMiyagi
@Chris_Rands,谢谢,这样更有意义了。reversed作为一个迭代器,并不会复制整个字符串。谢谢! - jpp
“''.join(...)”不是因为“调用两个函数”而变慢。它之所以变慢,是因为在Python运行时内部进行了迭代。 - wim
@wim 是的,这也是一个问题。但是使用这两个函数也有自己明显的开销。此外,请注意,在C或Python级别上进行迭代都会使程序变慢(增加复杂性),但重要的是在Python级别上发生的代码/解释量,这种情况下创建/解释等函数两次已经足够拖慢您的代码了。 - Mazdak

2

在内存效率方面没有显著的差异。由于字符串是不可变的,两种方法都必须复制整个数据。

要检查性能,您可以使用标准库中的timeit模块。切片明显更快,因为避免了Python代码中的迭代:

>>> s = "google"
>>> %timeit "".join(reversed(s))
612 ns ± 20.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> %timeit s[::-1]
157 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

运行时的提升对于更大的字符串来说是越来越明显:

>>> s = s*1000
>>> %timeit "".join(reversed(s))
119 µs ± 2.37 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit s[::-1]
10.8 µs ± 123 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

CPython 3.7.0b4 on macOS.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接