[Tutor] detecing palindromic strings

Terry Carroll carroll at tjc.com
Sat Sep 29 02:43:22 CEST 2007


On Fri, 28 Sep 2007, Christopher Spears wrote:

> I'm trying to write a script that detects if a string
> is palindromic (same backward as it is forward).  This
> is what I have so far:

> my_str = raw_input("Enter a string: ")
> string_list = []

Here you are creating a list and assiging the name string_list to it.

> for s in my_str:
>     string_list.append(s)

Now you've manipulated this list

> string_list_orig = string_list

Here is the problem: you're thinking you're creating another list, named 
string_list_orig, which is a copy of string_list.  you're not.  What 
you're actually doing is assigning another name, string_list_orig, to the 
existing list that was created above.

> string_list.reverse()

Now you're reversing that single list.

> print string_list_orig
> print string_list

Now you're printing that list twice, once using each name.

> 
> The problem is that the script gives results like so:
> io at io-station-1 ./chap6 117> python palindromic.py
> Enter a string: abc
> ['c', 'b', 'a']
> ['c', 'b', 'a']

Using your approach, the easiest quick fix is to replace the line:

 string_list_orig = string_list

with:

 string_list_orig = string_list[:]

This creates a new list by slicing from string_list, and assigns it a 
name string_list_orig.  Then you're dealing with two different lists, 
and reversing one does not affect the other.

The notation string_list[:] produces a slice of a list.  You usually see 
it with numbers in there, a la:

>>> L = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
>>> L[2:5]
['C', 'D', 'E']

This slices from position 2 up to (but not including) position 5. ('A' is 
at position 0).

The default for where to start is 0, so L[:5] is the same as L[0:5] :

>>> L[:5]
['A', 'B', 'C', 'D', 'E']

The default for where to end is the end of the list, so L[2:] is the same 
as L starting at 2 and going to the end of the list:

>>> L[2:]
['C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']

Putting those two defaults together, leaving both the start and end out 
means to start at the first element and go all the way to the end:

>>> L[:]
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']

So that's what the funky [:] notation gets you.

> How do I get around this?  Is there a better way to
> write this script?  I can't figure out how to loop
> through a string starting from the last character.

You can slice strings the same way you can slice lists.  And what's more, 
you can specify a third parameter on the slice that specifies the stepping 
of the slicing; the default is 1, but, for example, using 2 will select 
every other element:

>>> S = "ABCDEFGHIJ"
>>> S[::2]
'ACEGI'

And, here's the thing: if you use a negative number for ttep, it works 
from the right side of the string, rather than the left.  So, if you use a 
step of -1 you get:

>>> S[::-1]
'JIHGFEDCBA'

And that's the easiest way to reverse a string, rather than converting it 
to a list and reversing the list.




More information about the Tutor mailing list