59
votes

What is the best way to loop over a python string backwards?

The following seems a little awkward for all the need of -1 offset:

string = "trick or treat"
for i in range(len(string)-1, 0-1, -1):
    print string[i]

The following seems more succinct, but is it actually generate a reversed string so that there is a minor performance penalty?

string = "trick or treat"
for c in string[::-1]:
    print c
11
Is there any specific reason why you wrote 0-1 as the second parameter for range? When I tried to run this it works for simply -1. I was just curious to know whether it is just a writing convention or am I missing something. - newbie
@newbie I guess it's 0 that was later fixed to -1. - ivan_pozdeev

11 Answers

101
votes

Try the reversed builtin:

for c in reversed(string):
     print c

The reversed() call will make an iterator rather than copying the entire string.

PEP 322 details the motivation for reversed() and its advantages over other approaches.

9
votes

Here is a way to reverse a string without utilizing the built in features such as reversed. Negative step values traverse backwards.

def reverse(text):
    rev = ''
    for i in range(len(text), 0, -1):
        rev += text[i-1]
    return rev
5
votes

reversed takes an iterable and and returns an iterator that moves backwards. string[::-1] is fine, but it creates a new, reversed string instead. If you just want to iterate, then this will probably better:

for c in reversed(string):
    print c

If you want to use the reversed string afterwards, creating it once will be better.

4
votes

Yes, the second syntax shortcut creates an intermediate string and has an associated performance penalty.

The first version is better written as:

for index, char in enumerate(reversed(s)):
   print "pos %d: %s" % (index, char)

Which is easy to comprehend. Neither reversed nor enumerate` need to make a copy of the string.

Also be careful about using string as a variable name, as it is also the name of a module in the standard library.

3
votes
 string = "trick or treat"
 for c in string[::-1]:
     print c

I would use that. It is probably quite fast although there may be a slightly better way (but I doubt it).

EDIT: Actually, with a second test using a program I hacked together, reversed is probably the way to go.

 ==== Results ====
Sample 1: 0.0225071907043 # Using a for loop
Sample 2: 0.0100858211517 # Using reversed
3
votes

Less code is usually faster in Python. Luckily, you don't have to guess:

python -mtimeit -s"s='x'*100000" "for x in s[::-1]: pass"
100 loops, best of 3: 1.99 msec per loop

python -mtimeit -s"s='x'*100000" "for x in reversed(s): pass"
1000 loops, best of 3: 1.97 msec per loop

python -mtimeit -s"s='x'*100000" "for i in xrange(len(s)-1, 0-1, -1): s[i]"
100 loops, best of 3: 4.95 msec per loop

So the shorter code is a bit faster, but it comes with a memory overhead.

2
votes
string = "trick or treat"
for c in reversed(string):
    print c

Will do what I think you want. It uses an iterator. This should work with anything that has __reveresed__() or __len__() and __getitem__() implemented. __getitem__() would have to take int arguments starting at 0.

1
votes
def reverse(text):
    x = ""
    for i in range(len(text)):
        x = x + text[len(text)-i-1]
    return x
1
votes

Reverse a String in Python using For Loop

outputStr = ''
a = raw_input("Enter String: ")
for i in range(len(a), 0, -1):
    outputStr += a[i-1]
print outputStr
0
votes

Python 3 with enumerate and reversed methods:

string = "trick or treat"
for i, c in enumerate(reversed(string)):
    print(i, c)

You can use print(c) just for retrieving each character without the index.

-1
votes

string reverse

def reverse(a_string):
    rev = ''
    for i in range(len(a_string)-1, -1, -1):
        rev = rev + a_string[i]
    return rev
print(reverse("This string should be reversed!"))

output is: !desrever eb dluohs gnirts sihT