Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

invert or reverse a string... warning this is a rant

4 views
Skip to first unread message

rick

unread,
Oct 19, 2006, 11:47:38 AM10/19/06
to
Why can't Python have a reverse() function/method like Ruby?

Python:
x = 'a_string'
# Reverse the string
print x[::-1]

Ruby:
x = 'a_string'
# Reverse the string
print x.reverse

The Ruby approach makes sense to me as a human being. The Python
approach is not easy for me (as a human being) to remember. Can that be
changed or should I just start blindly memorizing this stuff?

P.S. I like Python better than Ruby 90% of the time and use Python 90%
of the time, but 10% of the time, little things such as this drive me crazy!

John Salerno

unread,
Oct 19, 2006, 12:00:03 PM10/19/06
to
rick wrote:
> Why can't Python have a reverse() function/method like Ruby?

I'm not steeped enough in daily programming to argue that it isn't
necessary, but my question is why do you need to reverse strings? Is it
something that happens often enough to warrant a method for it?

Paul Rubin

unread,
Oct 19, 2006, 12:09:49 PM10/19/06
to
rick <ath-...@vt.edu> writes:
> Why can't Python have a reverse() function/method like Ruby?
>
> Python:
> x = 'a_string'
> # Reverse the string
> print x[::-1]
>
> The Ruby approach makes sense to me as a human being. The Python
> approach is not easy for me (as a human being) to remember. Can that
> be changed or should I just start blindly memorizing this stuff?

You could use:

print ''.join(reversed(x))

That also looks a little bit weird, but it combines well-known Python
idioms straightforwardly.

Fredrik Lundh

unread,
Oct 19, 2006, 12:25:26 PM10/19/06
to pytho...@python.org
rick wrote:

> The Ruby approach makes sense to me as a human being.

do the humans on your planet spend a lot of time reversing strings?
it's definitely not a very common thing to do over here.

anyway, if you do this a lot, why not define a helper function?

def reverse(s):
return s[::-1]

print reverse("redael ruoy ot em ekat")

</F>

Demel, Jeff

unread,
Oct 19, 2006, 12:30:24 PM10/19/06
to pytho...@python.org
John Salerno wrote:
>'m not steeped enough in daily programming to argue that it
>sn't necessary, but my question is why do you need to
>reverse strings? Is it something that happens often enough
>to warrant a method for it?

I've been programming professionally for over 10 years, and have never
once needed to reverse a string. Maybe it's a lack of imagination on my
part, but I can't think of a single instance this might be necessary.

However, if I did ever run across this need while using Python, it would
seem awkward to use [::-1], just from a clarity standpoint. A
string.reverse() method would be a decent thing to have.

Just my $.02.

-Jeff

P.S. How about a string.shuffle() method that splits the string in half
into two new strings str1 and str2, and then recompiles the string by
alternating one character from each str1 and str2 as it goes? Like
shuffling cards. ;)
This email is intended only for the individual or entity to which it is addressed. This email may contain information that is privileged, confidential or otherwise protected from disclosure. Dissemination, distribution or copying of this e-mail or any attachments by anyone other than the intended recipient, or an employee or agent responsible for delivering the message to the intended recipient, is prohibited. If you are not the intended recipient of this message or the employee or agent responsible for delivery of this email to the intended recipient, please notify the sender by replying to this message and then delete it from your system. Any use, dissemination, distribution, or reproduction of this message by unintended recipients is strictly prohibited and may be unlawful.

Demel, Jeff

unread,
Oct 19, 2006, 12:35:53 PM10/19/06
to pytho...@python.org

Brad

unread,
Oct 19, 2006, 12:38:55 PM10/19/06
to

I'm home for lunch so my email addy is different.

No, it doesn't happen very often, but when I need to reverse something
(usually a list or a string). I can never remember right of the top of
my head how to do so in Python. I always have to Google for an answer or
refer back to old code.

IMO, I should be able to intuitively know how to do this. Python is so
user-friendly most every place else... why can it not be so here?

I wrote this so I'll never have to remember this again:

def invert(invertable_object):
try:
print invertable_object[::-1]
return invertable_object[::-1]
except:
print 'Object not invertable'
return 1

invert([1,2,3,4])
invert('string')
invert({1:2, 3:4})


Neil Cerutti

unread,
Oct 19, 2006, 12:45:54 PM10/19/06
to
On 2006-10-19, Brad <rti...@vt.edu> wrote:
> I'm home for lunch so my email addy is different.
>
> No, it doesn't happen very often, but when I need to reverse
> something (usually a list or a string). I can never remember
> right of the top of my head how to do so in Python. I always
> have to Google for an answer or refer back to old code.
>
> IMO, I should be able to intuitively know how to do this.
> Python is so user-friendly most every place else... why can it
> not be so here?
>
> I wrote this so I'll never have to remember this again:
>
> def invert(invertable_object):
> try:
> print invertable_object[::-1]
> return invertable_object[::-1]
> except:
> print 'Object not invertable'
> return 1
>
> invert([1,2,3,4])
> invert('string')
> invert({1:2, 3:4})

Shoot, now you'll have to remember where in heck you stashed that
function the next time you need to reverse something. ;-)

You'll still be better off in the long run memorizing the slice
notation.

--
Neil Cerutti

Brad

unread,
Oct 19, 2006, 12:46:50 PM10/19/06
to
Fredrik Lundh wrote:
> rick wrote:
>
>> The Ruby approach makes sense to me as a human being.
>
> do the humans on your planet spend a lot of time reversing strings? it's
> definitely not a very common thing to do over here.

On our planet, we're all dyslexic. We tend to do things 'backwards' so
being able to easily invert what we do helps the people we show the code
to on your planet make sense of it.

>
> anyway, if you do this a lot, why not define a helper function?
>
> def reverse(s):
> return s[::-1]
>
> print reverse("redael ruoy ot em ekat")

Thanks, that's what I ended up doing.

Paul McGuire

unread,
Oct 19, 2006, 1:03:42 PM10/19/06
to

"Demel, Jeff" <Jeff....@JavelinDirect.com> wrote in message
news:mailman.764.11612757...@python.org...

John Salerno wrote:
P.S. How about a string.shuffle() method that splits the string in half
into two new strings str1 and str2, and then recompiles the string by
alternating one character from each str1 and str2 as it goes? Like
shuffling cards. ;)


You mean:

"".join(sum(map(list,zip(s,s[len(s)/2:])),[]))

perhaps?

>>> s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
>>> "".join(sum(map(list,zip(s,s[len(s)/2:])),[]))
'ANBOCPDQERFSGTHUIVJWKXLYMZ'
>>>

-- Paul


Message has been deleted

Tim Chase

unread,
Oct 19, 2006, 1:30:04 PM10/19/06
to Demel, Jeff, pytho...@python.org
> P.S. How about a string.shuffle() method that splits the string in half
> into two new strings str1 and str2, and then recompiles the string by
> alternating one character from each str1 and str2 as it goes? Like
> shuffling cards. ;)

Well, for a true shuffling of a string, there's a
random.shuffle() but it chokes on strings. You have to do a
little song-and-dance to get a shuffled string:

>>> import random
>>> s = "hello world?"
>>> a = list(s)
>>> random.shuffle(a)
>>> s2 = ''.join(a)
>>> s2
'wlhlldor oe?'

Not quite the same algorithm you used. That would be something like

>>> "".join(sum(map(list,zip(s,s[len(s)/2:])),[]))

(my first attempt:

>>> "".join(sum(map(list,zip(s[0:len(s)/2],s[len(s)/2:])),[]))

had problems when the list didn't contain an even number of chars)

-tkc


Fredrik Lundh

unread,
Oct 19, 2006, 1:47:37 PM10/19/06
to pytho...@python.org
Dennis Lee Bieber wrote:

> ONE usage... The old intro-to-programming Palindrome detector
> becomes a very simple assignment given an easy means of reversing a
> string (vs the "expected" loop comparing from the ends in to the center)

you mean like

>>> s = "a man a plan a canal panama"
>>> if list(s) != list(reversed(s)):
... print repr(s), "is not a palindrome"
...
'a man a plan a canal panama' is not a palindrome

?

</F>

Demel, Jeff

unread,
Oct 19, 2006, 1:54:14 PM10/19/06
to pytho...@python.org
wlf...@ix.netcom.com wrote:
>ONE usage... The old intro-to-programming Palindrome detector
>becomes a very simple assignment given an easy means of
>reversing a string (vs the "expected" loop comparing from
>the ends in to the center)

Ok, let me re-phrase:

...[snip]...


I've been programming professionally for over 10 years, and have never

once needed to reverse a string *or detect a palindrome*. Maybe it's a


lack of imagination on my part, but I can't think of a single instance
this might be necessary.

...[snip]...

;)

Those damn "intro-to-programming" classes nail me again! Is this why
the applicants I see that are fresh out of college with their shiny new
computer science degrees can't seem to code their way out of a wet paper
bag?

-Jeff

James Stroud

unread,
Oct 19, 2006, 1:56:37 PM10/19/06
to
John Salerno wrote:
> rick wrote:
>
>> Why can't Python have a reverse() function/method like Ruby?
>
>
> I'm not steeped enough in daily programming to argue that it isn't
> necessary, but my question is why do you need to reverse strings?

It would provide symmetry for reversing any sequence (without requiring
an iterator).

(1,2,3).reversed()

"123".reversed()

[1,2,3].reversed()

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/

rick

unread,
Oct 19, 2006, 1:58:46 PM10/19/06
to
Demel, Jeff wrote:
> Ok, let me re-phrase:
>
> ...[snip]...
> I've been programming professionally for over 10 years, and have never
> once needed to reverse a string *or detect a palindrome*. Maybe it's a
> lack of imagination on my part, but I can't think of a single instance
> this might be necessary.
> ...[snip]...

I read files backwards all the time. Just for the heck of it. Now, maybe
I don't *need* to do this, but I do and I'd like to be able to do so
like this:

x = open('file_name')
print x.read().reverse()
*OR* print reverse(x.read())
x.close()

To me, that makes sense. Of course, like I said earlier, I think backwards.

Tim Chase

unread,
Oct 19, 2006, 2:13:21 PM10/19/06
to Demel, Jeff, pytho...@python.org
> Is this why the applicants I see that are fresh out of college
> with their shiny new computer science degrees can't seem to
> code their way out of a wet paper bag?

Well, there you go! Apparently, your wet paper bag has no
"detect a palendrome" exit. While you're installing such an
egress to your soggy dead-tree satchel, you could also provide
similar "write a binary search" or "write your own linked-list
implementation" escape hatches... :)

-tkc

J. Clifford Dyer

unread,
Oct 19, 2006, 2:14:33 PM10/19/06
to
Demel, Jeff wrote:

> P.S. How about a string.shuffle() method that splits the string in half
> into two new strings str1 and str2, and then recompiles the string by
> alternating one character from each str1 and str2 as it goes? Like
> shuffling cards. ;)

Jeff,

To my mind that would be the exact opposite of shuffling a deck of
cards. In your case, each time, you know exactly which stack the card
comes from, but not which card out of the stack. When you shuffle
cards, it's more like you know exactly which card is coming next off of
each stack, you just don't know which stack it's pulling from next.

import random

def shuffle(seq):
midpoint = len(seq)/2
stack1 = seq[:midpoint]
stack2 = seq[midpoint:]
shuffled = []
while stack1 and stack2:
next = random.choice((stack1, stack2))
shuffled.append(next.pop())
if stack1:
shuffled.extend(stack1)
else:
shuffled.extend(stack2)
return shuffled

rick

unread,
Oct 19, 2006, 2:18:18 PM10/19/06
to
Tim Chase wrote:

> Well, there you go! Apparently, your wet paper bag has no "detect a
> palendrome" exit. While you're installing such an egress to your soggy
> dead-tree satchel, you could also provide similar "write a binary

Glad you guys are enjoying this. We're getting off-topic and I think my
point is being lost to jest.

As humans, we know very little. But one of the basics of our knowledge
is order or sequence. 1,2,3,4 is natural so is 4,3,2,1 (count down to
blast off for example). When we put our shirt on inside-out or watch
someone moon walk (Micheal Jackson) it's immediately obvious and easy to
see that the sequence is reversed. Backwards is pure, simple and easy.
This is not so in Python and it should be.

That's all I have to day about that.

Paul Boddie

unread,
Oct 19, 2006, 2:41:21 PM10/19/06
to
James Stroud wrote:
>
> It would provide symmetry for reversing any sequence (without requiring
> an iterator).
>
> (1,2,3).reversed()
>
> "123".reversed()
>
> [1,2,3].reversed()

That might infuriate those who regard strings as "mischievous"
sequences (ie. things which cause errors because you think you have a
list, but you're actually accessing characters in a string), but it's a
valid point: the built-in sequence types should, within reason, provide
a similar interface.

The proposed solution involving slicing syntax does seem odd in the
sense that it's highly similar to the redundant-for-strings s[:]
operation, and it might require inspiration for anyone looking for
convenience methods on the string object to consider using slicing
instead in this manner. In looking for alternative approaches, I became
somewhat distracted by the classic approach you'd use with certain
functional languages: convert the string into a list of characters (if
it isn't already treated as a list), reverse the list, concatenate the
list. The following requires Python 2.4:

"".join(list(reversed(list(s))))

I guess Python 2.5 has the reversed method of which you speak. Still,
the simplest things are often the best, and Python's classic operators
(indexing, slicing) should always be kept in mind.

Paul

James Stroud

unread,
Oct 19, 2006, 2:54:22 PM10/19/06
to
Paul Boddie wrote:

> James Stroud wrote:
>>(1,2,3).reversed()
>>
>>"123".reversed()
>>
>>[1,2,3].reversed()
>
> I guess Python 2.5 has the reversed method of which you speak.

Not that I could find (as methods of any built in sequence type). 2.5
just has the "reversed" function that returns and iterator and so 2.5
requires these kind of gymnastics on built in sequences:

> "".join(list(reversed(list(s))))

Of course, I think str.join can operate on iterators, as Paul Rubin
suggests:

> print ''.join(reversed(x))

This latter approach still seems a little clunky, though.

James

Ron Adam

unread,
Oct 19, 2006, 2:59:52 PM10/19/06
to
James Stroud wrote:

> Of course, I think str.join can operate on iterators, as Paul Rubin
> suggests:
>
> > print ''.join(reversed(x))
>
> This latter approach still seems a little clunky, though.
>
> James

Slices can be named so you could do...

>>> reverser = slice(None, None, -1)
>>>
>>> 'abcdefg'[reverser]
'gfedcba'


Ron

Fredrik Lundh

unread,
Oct 19, 2006, 3:15:04 PM10/19/06
to pytho...@python.org
James Stroud wrote:

> without requiring an iterator

can we perhaps invent some more arbitrary constraints while we're at it?

</F>

Fredrik Lundh

unread,
Oct 19, 2006, 3:17:38 PM10/19/06
to pytho...@python.org
rick wrote:

natural = 1, 2, 3, 4
for item in reversed(natural):
print item
print "badabom!"

> That's all I have to day about that.

thank you.

</F>

James Stroud

unread,
Oct 19, 2006, 3:52:40 PM10/19/06
to

Why does it seem to me that you are confusing convienience with
constraint, or are the two equivalent?

James

Neil Cerutti

unread,
Oct 19, 2006, 3:54:14 PM10/19/06
to

No letter G. I don't like them. They wet their nests.

--
Neil Cerutti
You only get a once-in-a-lifetime opportunity so many times.
--Ike Taylor

James Stroud

unread,
Oct 19, 2006, 4:32:30 PM10/19/06
to

I guess while I'm at it, this thread wouldn't have so much steam were
these idioms seemingly unpythonic:

"".join(reverse(x))
alist[::-1]

The latter, while more terse than alist.reversed(), is unnatural and
ugly compared to the general elegance of other constructs in python.
Were this not the case, beginners and intermediate programmers alike
would not have such trouble remembering it. In fact, the latter's exact
behavior, if I remember correctly, spawned a thread of its own with much
speculation as to the exact meaning of the documentation and whether the
API conformed to this inferred meaning. I'll attempt to provide a link
to the thread if anyone takes me to task on this.

I'm sure many life-long programmers will claim that they have never
created a reverse copy of a data structure for production code, but why
is it that so many jump to the fore to point out that alist[::-1] is how
one produces a reverse copy of a list, or that a string can be reversed
with reversed, join, and an instance of another string (did I leave
something out?)?

But why do so many beginning programmers ask how one might produce a
reverse data structure in python? Perhaps they are just ignorant fools
who don't know that creating a reverse copy of a data structure can be
proven to be a useless operation if only they would stop trying to write
code and begin to write formal proofs. Perhaps their professors are to
blame, unreasonably asking them to write actual code before memorizing
all three+ volumes of Knuth. I'm sure the proof is in there somewhere.

But maybe it is not the purpose of a poweful language like python to be
used as a teaching language. Maybe python should be reserved for use
only by those who have been desensitized to its idiosyncracies,
inconsistencies, and idiomatic workarounds.

James

James Stroud

unread,
Oct 19, 2006, 4:38:59 PM10/19/06
to
Neil Cerutti wrote:
> On 2006-10-19, Fredrik Lundh <fre...@pythonware.com> wrote:
>
>>James Stroud wrote:
>>
>>
>>>without requiring an iterator
>>
>>can we perhaps invent some more arbitrary constraints while
>>we're at it?
>
>
> No letter G. I don't like them. They wet their nests.
>

The requirement for an iterator is the constraint. Removin the
requirement for the iterator removes the constraint. Or is the iterator
the convenience?

James

sk...@pobox.com

unread,
Oct 19, 2006, 4:59:03 PM10/19/06
to James Stroud, pytho...@python.org

James> I guess while I'm at it, this thread wouldn't have so much steam
James> were these idioms seemingly unpythonic:

James> "".join(reverse(x))
James> alist[::-1]

James> The latter, while more terse than alist.reversed(), is unnatural
James> and ugly compared to the general elegance of other constructs in
James> python. Were this not the case, beginners and intermediate
James> programmers alike would not have such trouble remembering it.

I've no comment one way or the other on the "".join() idiom. I realize a
lot of folks don't like it. The extended slice notation comes from the
numeric community though where they are probably all former FORTRAN
programmers. I think the concept of start, stop, step (or stride?) is
pretty common there. It also fairly nicely matches the arguments to range()
and extends the list "copy operator" alist[:] in a more-or-less
straightforward fashion. It takes a little getting used to, but it's really
not all that hard to remember once you've seen it a couple times. Besides,
it's not obvious to me that simple sequence slicing would be all that
familiar to the uninitiated.

go-bruins-ly, y'rs,

Skip

Steven D'Aprano

unread,
Oct 19, 2006, 7:04:07 PM10/19/06
to
On Thu, 19 Oct 2006 12:38:55 -0400, Brad wrote:

> John Salerno wrote:
>> rick wrote:
>>> Why can't Python have a reverse() function/method like Ruby?
>>
>> I'm not steeped enough in daily programming to argue that it isn't
>> necessary, but my question is why do you need to reverse strings? Is it
>> something that happens often enough to warrant a method for it?
>
> I'm home for lunch so my email addy is different.
>
> No, it doesn't happen very often, but when I need to reverse something
> (usually a list or a string). I can never remember right of the top of
> my head how to do so in Python. I always have to Google for an answer or
> refer back to old code.
>
> IMO, I should be able to intuitively know how to do this. Python is so
> user-friendly most every place else... why can it not be so here?

I agree -- the reversed() function appears to be an obvious case of purity
overriding practicality :(

>>> str(reversed("some string"))
'<reversed object at 0xb7edca4c>'
>>> repr(reversed("some string"))
'<reversed object at 0xb7edca4c>'

Not very useful.

The simplest ways to get a reversed string seem to be:

>>> "some string"[::-1]
'gnirts emos'
>>> ''.join(list(reversed("some string")))
'gnirts emos'

neither of which are exactly intuitive, but both are standard Python
idioms.

> I wrote this so I'll never have to remember this again:
>
> def invert(invertable_object):
> try:
> print invertable_object[::-1]
> return invertable_object[::-1]
> except:
> print 'Object not invertable'
> return 1

Gah!!! That's *awful* in so many ways.

(1) The name is bad. "invert" is not the same as "reverse". Here's an
invert: 1/2 = 0.5. Your function falsely claims numbers aren't invertable.

(2) Why calculate the reversed object twice?

(3) It is poor practice to have the same function both *print* the result
and *return* the result. What happens when you want the reversed object,
but you don't want it to print? You either write a new function, or you
muck about capturing output and hiding it. You should return the result,
and leave it up to the caller to print if they want to print.

(That's a complaint I have about the dis module -- it prints its results,
instead of returning them as a string. That makes it hard to capture the
output for further analysis.)

(4) Why are you capturing Python's perfectly good and useful traceback,
and printing an unhelpful error message?

(5) Errors should raise exceptions, not return "magic numbers" like 1. 1
is not an error-state, it is perfectly fine output. Now you have to
remember that your invert function returns 1 on error, and calling code
has to check for it:

list_of_reversed_object = []
for obj in list_of_objects_to_reverse:
temp = invert(obj)
if temp == 1:
raise ValueError("invalid object")
# or do something else...
list_of_reversed_objects.append(temp)

Compare:

list_of_reversed_object = []
for obj in list_of_objects_to_reverse:
list_of_reversed_objects.append(invert(obj))


Or if you want to skip invalid objects:

list_of_reversed_object = []
for obj in list_of_objects_to_reverse:
try:
list_of_reversed_objects.append(invert(obj))
except SomeError:
pass

--
Steven.

Paul Rubin

unread,
Oct 19, 2006, 7:34:46 PM10/19/06
to
Steven D'Aprano <st...@REMOVE.THIS.cybersource.com.au> writes:
> >>> ''.join(list(reversed("some string")))
> 'gnirts emos'

''.join(reversed('some string')) should work, without building the
intermediate list.

I generally don't remember the ::-1 syntax so the above would occur to
me sooner.

Brad

unread,
Oct 19, 2006, 8:07:27 PM10/19/06
to
Steven D'Aprano wrote:

> Gah!!! That's *awful* in so many ways.

Thanks... I'm used to hearing encouragement like that. After a while you
begin to believe that everything you do will be awful, so why even
bother trying?

<rant>

It has been my experience that Python has discouraging forums with
someone always calling someone else an idiot or telling them they are
awful in some way. I love Python, but the community is way too negative,
uptight and generally down on users who do not have PhD's in CS or Math.

Do you have children? How would your child feel if he brought you
something he had made and you then told him it was awful in *sooo* many
ways. How does that reflect on you and the community you represent?

Cut people who don't think like you some slack, OK?

</rant>

> (1) The name is bad. "invert" is not the same as "reverse". Here's an
> invert: 1/2 = 0.5. Your function falsely claims numbers aren't invertable.

Dictionary.com
invert = to reverse in position, order, direction, or relationship.

It matters not that a sequence is thought of as being from left to
right, top to bottom or right to left, does it? Read the sequence as you
normally would (however that may be) and then invert it or read it in
reverse to begin with.

I apologize for bringing this up. Thanks for your time.

Gabriel Genellina

unread,
Oct 19, 2006, 9:22:34 PM10/19/06
to Brad, pytho...@python.org
At Thursday 19/10/2006 21:07, Brad wrote:

> > Gah!!! That's *awful* in so many ways.
>

>It has been my experience that Python has discouraging forums with
>someone always calling someone else an idiot or telling them they are
>awful in some way. I love Python, but the community is way too negative,
>uptight and generally down on users who do not have PhD's in CS or Math.

I agree with you being angry.
It's true that our posts are going to stay for a long time, and
people could find and read them, and perhaps copy and use our posted
code. So when something is not up-to-the-standard or not following
the best practices or is not the best way of doing things, that
should be noted.
Certainly there is no need to be rude! Pointing out the deficiencies
and how to avoid them can be done in a kind manner.
But I don't think that "the community" in general is too negative.
It's a lot more "newbie-friendly" than other popular language's.

> > (1) The name is bad. "invert" is not the same as "reverse". Here's an
> > invert: 1/2 = 0.5. Your function falsely claims numbers aren't invertable.
>
>Dictionary.com
>invert = to reverse in position, order, direction, or relationship.

Note that even on a mathematical sense, "inverse" does not mean only
"multiplicative inverse". -3 is the "additive inverse" of 3, by
example (See <http://mathworld.wolfram.com/AdditiveInverse.html>).
(BTW, integers -except two of them- are not inversible in Z).
So "invert" is not a bad name "per se". But having the reversed()
builtin and reverse() list method implies that a similarly rooted
name would be better (just to be coherent!) - perhaps reversed_string()?


--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam Ągratis!
ĄAbrí tu cuenta ya! - http://correo.yahoo.com.ar

Rainy

unread,
Oct 19, 2006, 11:41:40 PM10/19/06
to

Brad wrote:
> John Salerno wrote:
> > rick wrote:
> >> Why can't Python have a reverse() function/method like Ruby?
> >
> > I'm not steeped enough in daily programming to argue that it isn't
> > necessary, but my question is why do you need to reverse strings? Is it
> > something that happens often enough to warrant a method for it?
>
> I'm home for lunch so my email addy is different.
>
> No, it doesn't happen very often, but when I need to reverse something
> (usually a list or a string). I can never remember right of the top of
> my head how to do so in Python. I always have to Google for an answer or
> refer back to old code.
>
> IMO, I should be able to intuitively know how to do this. Python is so
> user-friendly most every place else... why can it not be so here?
>
> I wrote this so I'll never have to remember this again:
>
> def invert(invertable_object):
> try:
> print invertable_object[::-1]
> return invertable_object[::-1]
> except:
> print 'Object not invertable'
> return 1
>
> invert([1,2,3,4])
> invert('string')
> invert({1:2, 3:4})

A sequence can be reversed with a .reverse() method. For my needs, in 7
years of programming, I never needed to reverse a string. I think it
sounds like a reasonable rule of thumb to set aside things that you do
fairly often (let's say at least once a week or once in two weeks as
you write code, on average), and make sure you have shortcuts for all
of them, ways to write them quickly and easily, and make it easy to
remember as well. All other things, things you do less often, need not
be done so quickly and easily. Otherwise, I think you'll end up with a
language that has too many built in functions, methods, ins, outs and
what have you's.

If I had to reverse a string I'd first try the reverse method (although
my immediate feeling would be that it's probably not there), and then
I'd use a few lines to make a list, reverse it and join it. I don't
usually use one-liners. I would reason to myself that once in a few
years it's not a hardship to use a couple extra lines of code.

But maybe I'm missing something and in some problem domain there is a
frequent need to reverse a string? I saw your comment about countdown
on a launch of a shuttle, but that's not convincing to me, to be
honest, because if you wished to do anything as you count down (i.e.
print the next second number), you'd just make a loop and you can make
range() command reverse, or you can just reverse the list it returns.

It's a little strange; you do get a feeling that reversing a string
might be useful sometime or other, but the only thing I can think of is
palindromes, as someone else mentioned, which is used in some
textbooks. However, isn't it a little silly to add a function or a
method to language to make each textbook example into a one-liner?

Hendrik van Rooyen

unread,
Oct 20, 2006, 1:57:05 AM10/20/06
to pytho...@python.org
"Fredrik Lundh" <fre...@pythonware.com>wrote:
8<---------------------------

> 'a man a plan a canal panama' is not a palindrome
>
> ?

not if spaces count -

able was I ere I saw elba - is one - but its a tougher test...

- Hendrik

Hendrik van Rooyen

unread,
Oct 20, 2006, 2:34:00 AM10/20/06
to pytho...@python.org
"Brad" <rti...@vt.edu> wrote:


> Steven D'Aprano wrote:
>
> > Gah!!! That's *awful* in so many ways.
>
> Thanks... I'm used to hearing encouragement like that. After a while you
> begin to believe that everything you do will be awful, so why even
> bother trying?
>
> <rant>
>
> It has been my experience that Python has discouraging forums with
> someone always calling someone else an idiot or telling them they are
> awful in some way. I love Python, but the community is way too negative,
> uptight and generally down on users who do not have PhD's in CS or Math.
>
> Do you have children? How would your child feel if he brought you
> something he had made and you then told him it was awful in *sooo* many
> ways. How does that reflect on you and the community you represent?
>
> Cut people who don't think like you some slack, OK?
>
> </rant>

8<---------------------------------------------

This is kind of sad to see - what seems not be appreciated here is the genuine
effort that was put in by Stephen to critique the piece of code - not just a one
liner putdown, but a reasoned exposition, taking time...

and yes - it hurts at first to have your ego bruised - but look past that - and
see the genuine attempt to help.

- Hendrik


Simon Forman

unread,
Oct 20, 2006, 3:01:58 AM10/20/06
to
rick wrote:
...

> see that the sequence is reversed. Backwards is pure, simple and easy.
> This is not so in Python and it should be.

foo[::-1] isn't "pure, simple and easy"?

It derives cleanly from the slice notation, it does exactly what you
want, and it even works with lists and tuples and any other class
written to support slice notation.

Does ruby have a built in string function to do this: foo[::-2]? How
about this: foo[-1::-2] or this: foo[-2::-2]?

See, it's not about "blindly memorizing this stuff", it's about clever
abstractions that allow you to quickly, flexibly and powerfully program
your computer. I'd rather learn a few well thought out abstractions
than memorize a set of methods.

The answer to your OP question, "Why can't Python have a reverse()
function/method like Ruby?" is "It can." You can build it yourself
quickly and easily, and a lot of other functions as well.

Peace,
~Simon

I V

unread,
Oct 20, 2006, 3:29:24 AM10/20/06
to
On Fri, 20 Oct 2006 09:04:07 +1000, Steven D'Aprano wrote:
> I agree -- the reversed() function appears to be an obvious case of purity
> overriding practicality :(
>
>>>> str(reversed("some string"))
> '<reversed object at 0xb7edca4c>'
>>>> repr(reversed("some string"))
> '<reversed object at 0xb7edca4c>'

This doesn't seem particularly "pure" to me, either. I would
have thought str(some_iter) should build a string out of the iterator, as
list(some_iter) or dict(some_iter) do. I guess this might have to wait for
Python 3, but str ought to be a proper string constructor, not a "produce
a printable representation of" function, particularly when we have repr to
do the latter.

Demel, Jeff

unread,
Oct 19, 2006, 1:42:58 PM10/19/06
to pytho...@python.org
Paul wrote:
>"".join(sum(map(list,zip(s,s[len(s)/2:])),[]))
>
>perhaps?

Not quite as elegant as a "string.shuffle" would be, am I right?

Kay Schluehr

unread,
Oct 20, 2006, 3:48:22 AM10/20/06
to
> The Ruby approach makes sense to me as a human being.

http://happyfuncog.blogspot.com/2006/09/confessions-of-pseudo-misanthrope.html

> The Python approach is not easy for me (as a human being) to remember.

I always thought we Pythonistas are already idiots but whenever I meet
a Rubist it ( the human being ) appears completely retarded to me.

Fredrik Lundh

unread,
Oct 20, 2006, 4:03:49 AM10/20/06
to pytho...@python.org
"Brad" <rti...@vt.edu> wrote:

> Do you have children? How would your child feel if he brought you
> something he had made and you then told him it was awful in *sooo* many
> ways.

If you're arguing that everything a child does and says should be rewarded,
I seriously doubt that you have any.

(on the other hand, I didn't even have to tell my 3-year old that cutting the
whiskers off the kitten wasn't quite as clever as he had thought; he realized
that all by himself, but a bit too late for the poor animal...)

</F>

Fredrik Lundh

unread,
Oct 20, 2006, 4:04:54 AM10/20/06
to pytho...@python.org
Hendrik van Rooyen wrote:

>> 'a man a plan a canal panama' is not a palindrome
>

> not if spaces count -

which they do if you rely on a single reverse operation (my point was
that it takes a bit more work than that to check for a palindrome).

</F>

rick

unread,
Oct 20, 2006, 8:17:48 AM10/20/06
to
Fredrik Lundh wrote:
> "Brad" <rti...@vt.edu> wrote:
>
>> Do you have children? How would your child feel if he brought you
>> something he had made and you then told him it was awful in *sooo* many
>> ways.
>
> If you're arguing that everything a child does and says should be rewarded...


I'm not arguing that. Only that one should be polite and considerate
when giving advice. That's all.

foo[::-1] is acceptable. So is the helper function that you posted:

> def reverse(s):
> return s[::-1]

My 2 min hack is awful to some, and I'm OK with that and fully expect
it. But it works OK for me. Is there not room for solutions such as this
in Python?

No hard feelings. Let's close this thread. I'll accept the slicing and
memorize it.

Thanks guys.

Duncan Booth

unread,
Oct 20, 2006, 8:43:58 AM10/20/06
to
"Demel, Jeff" <Jeff....@JavelinDirect.com> wrote:

> I've been programming professionally for over 10 years, and have never
> once needed to reverse a string. Maybe it's a lack of imagination on my
> part, but I can't think of a single instance this might be necessary.

I did want to reverse some strings once, but it may have been nearly 10
years ago now.

If I remember correctly the situation was that I wanted to store a lot of
strings on a pda with limited memory and no gzip library. One way of
doing simple compression would be to store them sorted with the first byte
simply containing the number of characters in common with the previous
string. It happened that the strings in question had common suffixes more
than prefixes, so I stored them sorted by the reverse of the strings with a
lead byte containing the number of common characters at the tail of the
string.

Shortly afterwards I ported gzip to the target platform.

Tim N. van der Leeuw

unread,
Oct 20, 2006, 10:02:50 AM10/20/06
to

The failing of str(reversed('the string')) caught me off-guard too. I
think you're quite right that it would be good if str() becomes a
proper constructor.

In practice, the short-term fix would be to add a __str__ method to the
'reversed' object, and perhaps to all iterators too (so that trying to
build a string from an iterator would do the obvious thing).

Cheers,

--Tim

Fredrik Lundh

unread,
Oct 20, 2006, 10:17:09 AM10/20/06
to pytho...@python.org
Tim N. van der Leeuw wrote:

> In practice, the short-term fix would be to add a __str__ method to the
> 'reversed' object

so what should

str(reversed(range(10)))

do ?

> and perhaps to all iterators too (so that trying to build a string from an
> iterator would do the obvious thing).

all iterators? who's going to do that?

</F>

Carl Banks

unread,
Oct 20, 2006, 11:15:03 AM10/20/06
to

sk...@pobox.com wrote:
> The extended slice notation comes from the
> numeric community though where they are probably all former FORTRAN
> programmers. I think the concept of start, stop, step (or stride?) is
> pretty common there.

Yep. I do a bit of numerical work and the meaning of abc[::-1] is
plain as day to me.

One thing I'd like to point out is that few people seem to be thrown
off when slices are used to twiddle list elements. A few days back
there was a thread about reordering a list such as [1,2,3,4,5,6,7,8,9]
as [1,4,7,2,5,8,3,6,9], and the advice was along the lines of
a[0::3]+a[1::3]+a[2::3]. I don't remember any complaints about the the
notation there.

I think the problem here isn't the slice notation; it's the use of
slice notation for something that seems conceptually distinct. People
who aren't used to doing a lot of slicing don't always have the
connection between "reversing" and "slicing" in mind. It wouldn't
occur to them to accomplish a reverse with a slice, and it would
surprise them a bit to see it.


Carl

Carl Banks

unread,
Oct 20, 2006, 11:27:17 AM10/20/06
to

Demel, Jeff wrote:
> I've been programming professionally for over 10 years, and have never
> once needed to reverse a string. Maybe it's a lack of imagination on my
> part, but I can't think of a single instance this might be necessary.

Say you're using a function from a third-party library that finds the
first character in a string that meets some requirement. You need to
find the last such character.


Carl

Demel, Jeff

unread,
Oct 20, 2006, 11:49:30 AM10/20/06
to pytho...@python.org
>Demel, Jeff wrote:
>> I've been programming professionally for over 10 years, and have
never
>> once needed to reverse a string. Maybe it's a lack of imagination on

>> my part, but I can't think of a single instance this might be
necessary.

Carl wrote:
>Say you're using a function from a third-party library that finds
>the first character in a string that meets some requirement. You
>need to find the last such character.

It appears your imagination is better than mine.

Tim N. van der Leeuw

unread,
Oct 20, 2006, 11:55:24 AM10/20/06
to

Fredrik Lundh wrote:
> Tim N. van der Leeuw wrote:
>
> > In practice, the short-term fix would be to add a __str__ method to the
> > 'reversed' object
>
> so what should
>
> str(reversed(range(10)))
>
> do ?
>

My idea was that reversed.__str__() would do something like the
equivalent of ''.join(reversed(...))

Playing in the interactive shell with that idea I quickly realized that
this would of course consume the iterator as a side-effect... Which is
most likely to be undesirable.

(It works well if you just write it as in the examples above, where the
'reversed' object is temporary and instantly thrown away. But if you
assign the iterator object, in this case 'reversed', to an instance
variable then it should be immediately obvious that having the iterator
consumed as side-effect of calling it's __str__ method is very, very
wrong...)


> > and perhaps to all iterators too (so that trying to build a string from an
> > iterator would do the obvious thing).
>
> all iterators? who's going to do that?
>

It's not as easy as I expected. But if we could come up with a
reasonable way to create a __str__ method for iterators, well who knows
I might give it a go. (It would be my first C code in many years
though)


> </F>

Cheers,

--Tim

Istvan Albert

unread,
Oct 20, 2006, 12:26:35 PM10/20/06
to
Carl Banks wrote:

> Say you're using a function from a third-party library that finds the
> first character in a string that meets some requirement. You need to
> find the last such character.

You seem to imply that invoking a function on a reversed input is
somehow a generic solution to the problem (finding first vs finding
last) that you describe above above.

That would be the exception rather than the rule.

i.

egbert

unread,
Oct 20, 2006, 9:25:55 AM10/20/06