It feels so good, so quick and not C!

Steven Taschuk staschuk at
Tue Mar 18 06:26:21 CET 2003

Quoth BB:
>   Anyway, I throwing this piece of code into the arena to be kicked about -
> I hope to learn even more this way.

A commendable philosophy!

> print "This is a prompt. Enter a string to be reversed: ",
> sOrig = raw_input()#get a string to work on
> sRev=""#init
> char_count=len(sOrig)#now I have the string length
> while ((char_count - 1) >= 0):#loop thru string backwards, zero based
>    char_count = char_count - 1
>    sRev = sRev+sOrig[char_count]#create the reverse string
> print sRev

Some other techniques for you to consider.  (These are mostly for
educational value only.)

First, rather than using a while loop to count through a range of
integers, use a for loop and let range() do your counting for you
-- that's why it's there.

    def strrev(orig):
        rev = ''
        for i in range(len(orig)-1, -1, -1):
            rev = rev + orig[i]
        return rev

    def strrev(orig):
        rev = ''
        for i in range(len(orig)):
            rev = rev + orig[-i-1]
        return rev

    def strrev(orig):
        rev = ''
        for i in range(-1, -len(orig)-1, -1):
            rev = rev + orig[i]
        return rev

Imho the first example here is better than the other two: that
range(len(s)-1, -1, -1) invocation is good idiom.  (Corrections

But better still is to avoid all this nonsense with the indices by
iterating through the original string forwards, but building the
result string backwards:

    def strrev(orig):
        rev = ''
        for c in orig:
            rev = c + rev
        return rev

This should be no worse in terms of time or memory usage than the
previous versions; with strings, unlike with lists, you get no
advantage by "appending" instead of "inserting".  Since strings
are immutable, a new string must be created in either case (which
is why I scare-quote the terms here).

If strings *were* mutable, you would no doubt consider such things
as reversing the characters in place -- exchanging the first
character and the last, then the second and second-last, and so
forth, iterating inwards from both ends.

Any time you think "if strings were mutable...", stop and use a
list instead.  In this case, a glance in the documentation will
show that lists come with a ready-made reverse method, making the
problem trivial:

    def strrev(orig):
        rev = list(orig)
        return ''.join(rev)

This one is actually good technique, imho.

(If there were no list.reverse method, you could, of course, do it
yourself, perhaps like this:

    def strrev(orig):
        rev = list(orig)
        forwards = range(len(rev)//2)
        backwards = range(len(rev)-1, -1, -1)
        for a, b in zip(forwards, backwards):
            rev[a], rev[b] = rev[b], rev[a]
        return ''.join(rev)

If you're just learning Python, you might want to spend a few
minutes studying this version.  It has one slightly subtle point
for which I would write a comment if this were real code.)

Steven Taschuk             "The world will end if you get this wrong."
staschuk at     -- "Typesetting Mathematics -- User's Guide",
                                 Brian Kernighan and Lorrinda Cherry

More information about the Python-list mailing list