Reversing a string

Alex Martelli aleax at mac.com
Sun Jul 1 14:09:10 EDT 2007


Martin Durkin <nospam at williamsdurkin.co.uk> wrote:
   ...
> >>>>>> def rev(x):
> >>>             mylist = []
> >>>             for char in x:
> >>>                  mylist.append(char)
> >>>             mylist.reverse()
> >>>             for letter in mylist:
> >>>                  print letter
> >>> 
> >>> However, compare the incredible difference in clarity and elegance
> >>> between that and:
> >>> 
> >>>> >>> print "\n".join("spam"[::-1])
   ...
> >> OK, maybe I'm missing the point here as I'm new to Python. The first
> >> one seems clearer to me. What am I missing?
> >> 
> > I think all you are missing is familarity with Python, but I too don't
> > like one-liners simply for their own sake.
> 
> I guess that's it. The first one reads more like a textbook example which
> is about where I am at. Is there any speed benefit from the one liner?

The first example reads "excruciatingly low-level" to me: its autor is
thinking in terms of what the machine is doing, mapped into pretty
elementary low-level constructs.

The second example depends first of all on knowledge of extended-slicing
(specifically the fact that x[::-1] is a reversal, because of the
negative -1 "step" aka "stride").  If you don't know about extended
slicing, you're unlikely to just "get it from context", because it uses
a syntax based on punctuation rather than readable words whose meaning
you might guess at.  Python has a modest amount of such "punctuation
syntax" -- about the same amount as C but definitely more than Cobol
(where one would typically write "ADD a TO b" to avoid shocking totally
clueless readers with "mysterious punctuation" such as "a + b"...!!!-).
Punctuation is often very concise but not "intrinsically obvious" unless
you've been exposed to it already;-).

If I was targeting total newbies, since extended slicing is something
that they can well wait a while to learn, I'd probably compromise in
favor of "reversed(x)".  The "reversed" built-in function does basically
the same job as a [::-1] slicing, but any English speaker can probably
guess what it's doing -- presenting a reversed permutation of its
sequence argument.

So, something like:

for c in reversed(x): print c

is mostly likely how I'd present the solution to the task.  Using join
to make a single string is (in this particular case) needlessly
precious, though not really a big deal (and beginners had better learn
about joining pretty early on).  But that definitely does not justify
the excruciating, "micromanaged" nature of the first example, which
uselessly belabors the concept of "reversing" to a silly extent.

Python LETS you program at such lowish levels, if you insist, but it
encourages thinking more about your problem and less about the way the
inner gears of the machine will turn in order to produce a solution for
it...!  Part of the encouragement is indeed that coding at a higher
level of abstraction tends to make your program faster (an "abstraction
reward" to replace the "abstraction penalty" so common with some other
languages:-) -- but clarity and productivity are more important still.


Alex



More information about the Python-list mailing list