It feels so good, so quick and not C!

Steven Taschuk staschuk at telusplanet.net
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
welcomed.)

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)
        rev.reverse()
        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 telusplanet.net     -- "Typesetting Mathematics -- User's Guide",
                                 Brian Kernighan and Lorrinda Cherry





More information about the Python-list mailing list