Best way to loop over a python string backwards

Question:

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
Asked By: clwen

||

Answers:

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.

Answered By: Raymond Hettinger
 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
Answered By: AJ00200

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.

Answered By: Kenan Banks

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.

Answered By: Jochen Ritzel

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.

Answered By: Cat Plus Plus
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.

Answered By: krousey

EDIT: It has been quite some time since I wrote this answer. It is not a very pythonic or even efficient way to loop over a string backwards. It does show how one could utilize range and negative step values to build a value by looping through a string and adding elements in off the end of the string to the front of the new value. But this is error prone and the builtin function reversed is a much better approach. For those readers attempting to understand how reversed is implemented, take a look at the PEP, number 322, to get an understanding of the how and why. The function checks whether the argument is iterable and then yields the last element of a list until there are no more elements to yield. From the PEP:

[reversed] makes a reverse iterator over sequence objects that support getitem() and len().

So to reverse a string, consume the iterator until it is exhausted. Without using the builtin, it might look something like,

def reverse_string(x: str) -> str:
i = len(x)
while i > 0:
    i -= 1
    yield x[i]
    

Consume the iterator either by looping, eg

for element in (reverse_string('abc')): 
    print(element)

Or calling a constructor like:

cba = list(reverse_string('abc'))

The reverse_string code is almost identical to the PEP with a check removed for simplicity’s sake. In practice, use the builtin.

ORIGNAL ANSWER:

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
Answered By: Nathan
def reverse(text):
    x = ""
    for i in range(len(text)):
        x = x + text[len(text)-i-1]
    return x
Answered By: praveen

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
Answered By: Akshay Malhotra

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.

Answered By: ian0411

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

Answered By: Codruta Guler

If you care about performance, its best to not use reversed as this will generate a new string and an unnecessary function call. Instead, just iterate backwards through the string.

Eg. This will find last newline in a string:

s = 'abcdefgnxyz'
for i in range(len(s)-1, -1, -1):
    if s[i] == 'n':
        print('found \n at %s' % i)
        break

# found n at 7
Answered By: Timothy C. Quinn