By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,376 Members | 1,599 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,376 IT Pros & Developers. It's quick & easy.

Reversing a string

P: n/a
Yeah I know strings == immutable, but question 1 in section 7.14 of "How to
think like a computer Scientist" has me trying to reverse one.

I've come up with two things, one works almost like it should except that
every traversal thru the string I've gotten it to repeat the "list" again.
This is what it looks like:

Expand|Select|Wrap|Line Numbers
  1.         
  2.                         
  3.                         
  4.                 >>>mylist = []
  5. def rev(x):
  6.  
  7. for char in x:
  8. mylist.append(char)
  9. mylist.reverse()
  10. print mylist
  11.  
And the output that sorta works like it should, but threw a curveball, at me
looks like this:
>>rev("this is just a test")
['t']
['h', 't']
['i', 't', 'h']
['s', 'h', 't', 'i']
[' ', 'i', 't', 'h', 's']
['i', 's', 'h', 't', 'i', ' ']
['s', ' ', 'i', 't', 'h', 's', 'i']
[' ', 'i', 's', 'h', 't', 'i', ' ', 's']
['j', 's', ' ', 'i', 't', 'h', 's', 'i', ' ']
['u', ' ', 'i', 's', 'h', 't', 'i', ' ', 's', 'j']
['s', 'j', 's', ' ', 'i', 't', 'h', 's', 'i', ' ', 'u']
['t', 'u', ' ', 'i', 's', 'h', 't', 'i', ' ', 's', 'j', 's']
[' ', 's', 'j', 's', ' ', 'i', 't', 'h', 's', 'i', ' ', 'u', 't']
['a', 't', 'u', ' ', 'i', 's', 'h', 't', 'i', ' ', 's', 'j', 's', ' ']
[' ', ' ', 's', 'j', 's', ' ', 'i', 't', 'h', 's', 'i', ' ', 'u', 't', 'a']
['t', 'a', 't', 'u', ' ', 'i', 's', 'h', 't', 'i', ' ', 's', 'j', 's', ' ',
' ']
['e', ' ', ' ', 's', 'j', 's', ' ', 'i', 't', 'h', 's', 'i', ' ', 'u', 't',
'a', 't']
['s', 't', 'a', 't', 'u', ' ', 'i', 's', 'h', 't', 'i', ' ', 's', 'j', 's',
' ', ' ', 'e']
['t', 'e', ' ', ' ', 's', 'j', 's', ' ', 'i', 't', 'h', 's', 'i', ' ', 'u',
't', 'a', 't', 's']
So I figured maybe make it a generator (I'm not TO familiar with generators
yet so don't laugh) which changed my code just a slight bit:

Expand|Select|Wrap|Line Numbers
  1.         
  2.                         
  3.                         
  4.                 >>>mylist = []
  5. def rev(x):
  6.  
  7. for char in x:
  8. mylist.append(char)
  9. mylist.reverse()
  10. yield mylist
  11.  
But even that threw me a curveball:
>>rev("this is just a test")
<generator object at 0x00D52170>

So how on earth would be the best way to: Write a function that takes a
string as an argument and outputs the letters backward, one per line.

It should look like the first char of every list in the top "working" code.

Any help woould be greatly apreciated, and a little bit of explaination as
to why you did it the way you did would be more helpful than just the code.

Thanks in advance
Jun 27 '07 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Scott wrote:
So how on earth would be the best way to: Write a function that takes a
string as an argument and outputs the letters backward, one per line.
Homework?

Anyway, what about:

for c in string[::-1]:
print c
Stefan
Jun 27 '07 #2

P: n/a
On Wed, Jun 27, 2007 at 12:53:36PM -0400, Scott wrote:
So how on earth would be the best way to: Write a function that
takes a string as an argument and outputs the letters backward,
one per line.
>>def rev(forward):
... backward = list(forward)
... backward.reverse()
... return ''.join(backward)
>>rev("spam")
'maps'

list.reverse() changes the list in-place. Instead of iterating over
the items in the string sequence, you can just convert the input
string outright.

--

[Will Maier]-----------------[wi*******@ml1.net|http://www.lfod.us/]
Jun 27 '07 #3

P: n/a
Scott wrote:
Yeah I know strings == immutable, but question 1 in section 7.14 of "How
to think like a computer Scientist" has me trying to reverse one.

I've come up with two things, one works almost like it should except that
every traversal thru the string I've gotten it to repeat the "list" again.
This is what it looks like:

Expand|Select|Wrap|Line Numbers
  1.         
  2.                         
  3.                 >>>>mylist = []
  4. def rev(x):
  •  
  •             for char in x:
  •                 mylist.append(char)
  •                 mylist.reverse()
  •                 print mylist
  •  
  • <snip/>

    The reverse() is totally useless to apply each when appending each
    character. Not only useless, but faulty: if you have a even number of
    characters, your string won't be reversed.

    All you need to do is this:
    >>x = "abcdefg"
    print "".join(reversed(x))
    gfedcba
    HTH Diez
    Jun 27 '07 #4

    P: n/a

    "Scott" <s_*********@comcast.netwrote in message
    news:cY******************************@comcast.com. ..
    | Yeah I know strings == immutable, but question 1 in section 7.14 of "How
    to
    | think like a computer Scientist" has me trying to reverse one.
    >>'this is a test'[::-1]
    'tset a si siht'

    Jun 27 '07 #5

    P: n/a
    On 2007-06-27, Scott <s_*********@comcast.netwrote:
    Yeah I know strings == immutable, but question 1 in section
    7.14 of "How to think like a computer Scientist" has me trying
    to reverse one.
    No, it just wants to to print the characters in reverse, one per
    line.
    I've come up with two things, one works almost like it should
    except that every traversal thru the string I've gotten it to
    repeat the "list" again. This is what it looks like:
    >>>>mylist = []
    That's bad. If you need to use a list in the rev function, you
    should bind a new list to a local variable inside rev.
    >>>>def rev(x):
    for char in x:
    mylist.append(char)
    mylist.reverse()
    print mylist
    Here's an debugging exercise that you should try.

    Please explain what you think each line in the above is supposed
    to do. Pretend you are trying to convince me that the above
    program works correctly. I bet you will see find your errors
    right away as a result of this exercise.
    [/code]
    So I figured maybe make it a generator (I'm not TO familiar
    with generators yet so don't laugh) which changed my code just
    a slight bit:
    Experimentation with stuff you don't fully understand is a great
    way to learn, but not that useful for solving exercises. ;)

    --
    Neil Cerutti
    This team is one execution away from being a very good basketball team. --Doc
    Rivers
    Jun 27 '07 #6

    P: n/a
    ptn
    >>>mylist = []

    That's bad. If you need to use a list in the rev function, you
    should bind a new list to a local variable inside rev.
    He's right. If you want to use a list to temporarily store the
    reversed version of your string, it should exist only in the local
    namespace of your function.

    There's still stuff you can do with your function to make it work,
    such as:
    >>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])
    So, big lessons: (1) Global variables suck if you try to manipulate
    them and (2) in Python, if your code isn't as clear as you would like,
    there's probably a better way to do it.

    Jun 28 '07 #7

    P: n/a
    ptn <tn******@gmail.comwrote in news:1182997438.541012.54100
    @o61g2000hsh.googlegroups.com:
    >
    >>>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?

    Martin
    Jul 1 '07 #8

    P: n/a
    Martin Durkin <no****@williamsdurkin.co.ukwrote:
    >>>>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.

    Slicing is one of Pythons great features, but even experienced programmers
    often forget that you can have a third argument to a slice or that it can
    even be negative.

    The syntax for joining a sequence of strings with a separator is ugly, I
    sometimes prefer to write it out as:
    print str.join('\n', whatever)
    or:
    joinlines = '\n'.join
    ...
    print joinlines(whatever)

    but in this case I'd be as likely to go for an explicit loop for the print:

    def rev(x):
    for letter in x[::-1]:
    print letter

    which I think hits about the optimum between brevity and clarity. Your own
    optimum point may of course vary.
    Jul 1 '07 #9

    P: n/a
    Duncan Booth <du**********@invalid.invalidwrote in
    news:Xn*************************@127.0.0.1:
    Martin Durkin <no****@williamsdurkin.co.ukwrote:
    >>>>>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?
    thanks
    Martin

    Jul 1 '07 #10

    P: n/a
    Martin Durkin wrote:
    Duncan Booth <du**********@invalid.invalidwrote in
    news:Xn*************************@127.0.0.1:
    >Martin Durkin <no****@williamsdurkin.co.ukwrote:
    >>>>>>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?
    Almost definitely. But you can check yourself by using the timeit module.

    Stefan
    Jul 1 '07 #11

    P: n/a
    On 1 Jul 2007 11:09:40 GMT, Martin Durkin <no****@williamsdurkin.co.ukwrote:
    Duncan Booth <du**********@invalid.invalidwrote in
    news:Xn*************************@127.0.0.1:
    Martin Durkin <no****@williamsdurkin.co.ukwrote:
    >>>>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 one line is quite a bit faster:

    evan@thinkpad ~ $ python -m timeit 's = "onomatopoeia"; s = s.join(s[::-1])'
    100000 loops, best of 3: 6.24 usec per loop

    evan@thinkpad ~ $ python -m timeit '
    def rev(x):
    mylist = []
    for char in x:
    mylist.append(char)
    mylist.reverse()
    return "".join(mylist)

    s = "onomatopoeia"
    s = rev(s)'
    100000 loops, best of 3: 9.73 usec per loop

    --
    Evan Klitzke <ev**@yelp.com>
    Jul 1 '07 #12

    P: n/a
    Jay Loden <py****@jayloden.comwrote:
    ...
    For what it's worth, with python 2.5 on my Macbook:
    Hmmm, doesn't look to me as if it's worth much...:
    [jloden@macbook jloden]$ python -m timeit 's = "onomatopoeia"; s =
    s.join(s[::-1])'

    since what you're doing is...:
    >>s = "onomatopoeia"
    s = s.join(s[::-1])
    s
    'aonomatopoeiaionomatopoeiaeonomatopoeiaoonomatopo eiaponomatopoeiaoonoma
    topoeiatonomatopoeiaaonomatopoeiamonomatopoeiaoono matopoeianonomatopoeia
    o'
    >>>
    ....which isn't really just reversing the string, but quite a bit more
    work!-)
    Alex
    Jul 1 '07 #13

    P: n/a
    Alex Martelli wrote:
    Martin Durkin <no****@williamsdurkin.co.ukwrote:
    ...
    >>>>>>>>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;-).
    Since you mentioned Cobol I couldn't resist...

    move "spam" to spam
    Display Function Reverse(spam)

    There's also slicing (known in Cobol as "reference modification")
    move mystring(5:3) to my-newstring
    * moves 3 characters starting with character 5

    No "negative" slicing, though it could be simulated with Function
    Reverse() and ref.mod.

    Frank
    Jul 2 '07 #14

    P: n/a

    Alex Martelli wrote:
    since what you're doing is...:
    >>>s = "onomatopoeia"
    s = s.join(s[::-1])
    s
    'aonomatopoeiaionomatopoeiaeonomatopoeiaoonomatopo eiaponomatopoeiaoonoma
    topoeiatonomatopoeiaaonomatopoeiamonomatopoeiaoono matopoeianonomatopoeia
    o'

    ...which isn't really just reversing the string, but quite a bit more
    work!-)
    That's what I get for copying and pasting from the post preceding mine and not actually checking it for what it does ;)
    Jul 2 '07 #15

    P: n/a
    Jan Vorwerk <ja*********@cretin.frwrote:
    [ lots of sensible stuff to discover "reversed" ]
    >print reversed.__doc__
    See also:
    >>help(reversed)
    --
    \S -- si***@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/
    "Frankly I have no feelings towards penguins one way or the other"
    -- Arthur C. Clarke
    her nu becomež se bera eadward ofdun hlęddre heafdes bęce bump bump bump
    Jul 5 '07 #16

    P: n/a
    al***@mac.com (Alex Martelli) wrote in
    news:1i0pz5v.eftrpfbeilzpN%al***@mac.com:
    Aahz <aa**@pythoncraft.comwrote:
    >I would agree with people who claim
    that you should memorize most of the built-in functions (which is
    precisely why there is a high barrier to adding more built-in
    functions).

    I think the built-in functions and types a beginner is likely to need
    are a "fuzzy subset" (the decision of whether to include or exclude
    something being not really obvious:-) roughly including:

    abs all any bool chr cmp dict dir enumerate float getattr help hex int
    iter len list max min object open ord property raw_input reversed set
    sorted str sum tuple unichr unicode xrange zip
    Thanks guys, that is helpful.
    Jul 5 '07 #17

    This discussion thread is closed

    Replies have been disabled for this discussion.