您的位置:首页 > 编程语言 > Python开发

Python string reverse

2016-05-10 11:06 639 查看


Reverse
a string in Python

up
vote667down
votefavorite
191

There is no built in
reverse
function
in Python's
str
object.
What is the best way of implementing this?

If supplying a very concise answer, please elaborate on it's efficiency. Is the
str
converted
to a different object, etc.

python string
shareimprove
this question
edited May
28 '12 at 11:19





Teun Zengerink
2,62241928

asked May 31 '09 at 2:10





oneself
8,343185489

3
Not the best way by far, but one of the many ways to do it if you weren't allowed to use slicing or reversed(), is
''.join((s[i]
for i in xrange(len(s)-1, -1, -1)))
. – Dennis Mar
6 '13 at 6:49
add
a comment


14 Answers

activeoldestvotes

up vote1381down
voteaccepted
How about:
>>> 'hello world'[::-1]
'dlrow olleh'


This is extended slice syntax. It works by doing
[begin:end:step]
-
by leaving begin and end off and specifying a step of -1, it reverses a string.

shareimprove
this answer
edited Feb
25 '14 at 2:13





Mokolodi1
399

answered May 31 '09 at 2:11





Paolo Bergantino
271k62450403

85
That's very pythonic. Good job! – dionyziz Feb
22 '12 at 19:23
59
@PaoloBergantino You, sir, are a gentleman and a scholar. – TigOldBitties May
19 '12 at 15:43
89
Wow. I was horrified at first by the solution Paolo proposed, but that took a back seat to the horror I felt upon reading
the first comment: "That's very pythonic. Good job!" I'm so disturbed that such a bright community thinks using such cryptic methods for something so basic is a good idea. Why isn't it just s.reverse()? – odigity Feb
4 '13 at 19:49
46
@odigity: Perhaps until you understand Python you should reserve your judgment. – Paolo
Bergantino Feb
4 '13 at 20:37
52
Do I need to be a Python expert to have an opinion about the readability of code? – odigity Feb
4 '13 at 22:10
show 19 more
comments





up vote145down
vote
@Paolo's
s[::-1]
is
fastest; a slower approach (maybe more readable, but that's debatable) is
''.join(reversed(s))
.

shareimprove
this answer
edited Nov
29 '14 at 18:28





zadrozny
11210

answered May 31 '09 at 2:13





Alex Martelli
451k788281129

76
A lot faster: $ python -m timeit s='s = "abcdef"' 'mystr =
mystr[::-1]' 1000000 loops, best of 3: 0.263 usec per loop $ python -m timeit s='s = "abcdef"' 'mystr = "".join(reversed(mystr))' 100000 loops, best of 3: 2.29 usec per loop – telliott99 Jan
23 '10 at 17:55
1
Looks like about an order of magnitude faster. – Brian
Peterson Sep
22 '13 at 2:00
11
I prefer the "reversed()" solution. Readability counts. – guettli Dec
6 '13 at 13:21
2
@smci yes, his syntax is incorrect, the correct one is:
python
-mtimeit 'mystr="abcdef"' 'mystr = mystr[::-1]'
which yields 10000000 loops, best of 3: 0.142 usec per loop and
python
-mtimeit 'mystr="abcdef"' 'mystr = "".join(reversed(mystr))'
which yields 1000000 loops, best of 3: 0.669 usec per loop, on Python 3.4 , on a GNU/Linux system with Linux kernel 3.13.0-40-generic x86_64 and Intel Core 2 Duo CPU, T9300 @ 2.50GHz CPU – Mnemonic
Flow Dec
8 '14 at 22:10
1
@buzhidao, because
reversed
returns
an instance of
<type
'reversed'>
, not a string! – Alex
Martelli May
5 '15 at 23:23
show 2 more
comments
up vote19down
vote
Attempting a canonical answer for this question:

"There is no built in reverse function in Python's str object. What is the best way of implementing this?"

While
''.join(reversed('foo'))
is
readable, it requires calling a string method,
str.join
,
on another called function, which can be rather slow

Much faster is using a reverse slice:
'foo'[::-1]


But how can we make this more readable and understandable to someone less familiar with the intent of the original author? Let's create a named slice object, and pass it to the subscript notation.
start = stop = None
step = -1
reverse_slice = slice(start, stop, step)
'foo'[reverse_slice]


Implement as Function

To actually implement this as a function, I think it is semantically clear enough to simply use a descriptive name:
def reversed_string(a_string):
return a_string[::-1]


And usage is simply:
reversed_string('foo')


Demo of timings (differences are probably exacerbated by the shortness of the string being reversed):
>>> min(timeit.repeat("''.join(reversed('foo'))"))
2.2613844704083021
>>> min(timeit.repeat("'foo'[::-1]"))
0.28049658041891234
>>> min(timeit.repeat("start=stop=None; step=-1; 'foo'[start:stop:step]"))
0.37622163503510819
>>> min(timeit.repeat("start=stop=None; step=-1; reverse_slice = slice(start, stop, step); 'foo'[reverse_slice]"))
0.54768217598029878


And for the function:
>>> def reversed_string(a_string):
...     return a_string[::-1]
...
>>> min(timeit.repeat("reversed_string('foo')", 'from __main__ import reversed_string'))
0.47710669976368081


shareimprove
this answer
edited Aug
13 '15 at 1:05

answered Jan 8 '15 at 15:32





Aaron Hall
40.8k16119121

2
These are bad benchmarks. You shouldn't time the creation of the slice object. So this leads to really interesting results:
min(timeit.repeat("'foo'[reverse_slice]",
setup="reverse_slice = slice(None, None, -1)"))
is actually faster than
'foo'[::-1]
.
And a
reverse_string
function
using a global defined
reverse_slice
is
almost as fast as
'foo'[::-1]
. – schlamar Jan
28 '15 at 10:20
1
Most Python programmers prefer to use as few globals as possible. I can't imagine anyone using a global slice object
instead of the alternatives, and since a slice object is created by slice notation (see the CPython source hg.python.org/cpython/file/2.7/Objects/stringobject.c#l1307)
inside the subscript, it does seem fair to compare it within the function. Yes the slice object creation is much slower with the callable constructor, but I'm comparing apples to apples with realistic code. – Aaron
Hall Jan
28 '15 at 13:28
1
From a naming perspective, "reversed_string" may be clearer since it doesn't imply mutation. It sounds like "give me
the reversed version of this string" as opposed to "please reverse this string." Much like "sorted" (which returns a sorted list) or random.shuffle (which shuffles the list in place) – iAdjunct Jun
26 '15 at 4:38
@iAdjunct that's a very good suggestion, I've taken your advice. – Aaron
Hall Aug
13 '15 at 1:06
add
a comment
up vote10down
vote


Quick Answer (TL;DR)


Example

### example01 -------------------
mystring  =   'coup_ate_grouping'
backwards =   mystring[::-1]
print backwards

### ... or even ...
mystring  =   'coup_ate_grouping'[::-1]
print mystring

### result01 -------------------
'''
gnipuorg_eta_puoc
'''


Detailed Answer


Background

This answer is provided to address the following concern from a user odigity:

Wow. I was horrified at first by the solution Paolo proposed, but that took a back seat to the horror I felt upon reading the first comment: "That's very pythonic. Good job!" I'm so disturbed that such a bright community thinks using such cryptic methods for
something so basic is a good idea. Why isn't it just s.reverse()?


Problem

Context

Python 2.x
Python 3.x

Scenario:

Developer wants to transform a string
Transformation is to reverse order of all the characters


Solution

example01 produces the desired result, using extended
slice notation.


Pitfalls

Developer might expect something like
string.reverse()

The native idiomatic (aka "pythonic")
solution may not be readable to newer developers
Developer may be tempted to implement his or her own version of
string.reverse()
to
avoid slice notation.
The output of slice notation may be counter-intuitive in some cases:

see e.g., example02

print
'coup_ate_grouping'[-4:] ## => 'ping'

compared to
print
'coup_ate_grouping'[-4:-1] ## => 'pin'

compared to
print
'coup_ate_grouping'[-1] ## => 'g'


the different outcomes of indexing on
[-1]
may
throw some developers off


Rationale

Python has a special circumstance to be aware of: a string is an iterable type.

One rationale for excluding a
string.reverse()
method
is to give python developers incentive to leverage the power of this special circumstance.

In simplified terms, this simply means each individual character in a string can be easily operated on as a part of a sequential array of elements, just like arrays in other programming languages.

To understand how this works, reviewing example02 can provide a good overview.


Example02

### example02 -------------------
## start (with positive integers)
print 'coup_ate_grouping'[0]  ## => 'c'
print 'coup_ate_grouping'[1]  ## => 'o'
print 'coup_ate_grouping'[2]  ## => 'u'

## start (with negative integers)
print 'coup_ate_grouping'[-1]  ## => 'g'
print 'coup_ate_grouping'[-2]  ## => 'n'
print 'coup_ate_grouping'[-3]  ## => 'i'

## start:end
print 'coup_ate_grouping'[0:4]    ## => 'coup'
print 'coup_ate_grouping'[4:8]    ## => '_ate'
print 'coup_ate_grouping'[8:12]   ## => '_gro'

## start:end
print 'coup_ate_grouping'[-4:]    ## => 'ping' (counter-intuitive)
print 'coup_ate_grouping'[-4:-1]  ## => 'pin'
print 'coup_ate_grouping'[-4:-2]  ## => 'pi'
print 'coup_ate_grouping'[-4:-3]  ## => 'p'
print 'coup_ate_grouping'[-4:-4]  ## => ''
print 'coup_ate_grouping'[0:-1]   ## => 'coup_ate_groupin'
print 'coup_ate_grouping'[0:]     ## => 'coup_ate_grouping' (counter-intuitive)

## start:end:step (or stop:end:stride)
print 'coup_ate_grouping'[-1::1]  ## => 'g'
print 'coup_ate_grouping'[-1::-1] ## => 'gnipuorg_eta_puoc'

## combinations
print 'coup_ate_grouping'[-1::-1][-4:] ## => 'gnipuorg_eta_puoc'


Conclusion

The cognitive load associated with understanding how slice notation works in python may indeed
be too much for some adopters and developers who do not wish to invest much time in learning the language.

Nevertheless, once the basic principles are understood, the power of this approach over fixed string manipulation methods can be quite favorable.

For those who think otherwise, there are alternate approaches, such as lambda functions, iterators, or simple one-off function declarations.

If desired, a developer can implement her own string.reverse() method, however it is good to understand the rationale behind this "quirk" of python.


See also

alternate simple approach
alternate simple approach
alternate
explanation of slice notation

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: