0

Can anybody tell me why Python considers my palindrome list as not the same as the same palindrome list reversed? For example, when I enter the word THHT (a palindrome), I get a negative result.

word=input("Input a word: ")
word_check=list()
a=list()
i=0
while i<len(word):
    word_check.append(word[i])
    i+=1

if word_check==word_check.reverse():
    print("The word is a palindrome")
else:
    print("The word is not a palindrome")
Grismar
  • 27,561
  • 4
  • 31
  • 54
  • You can just use `word_check = list(word)` to convert the string to a list of characters. – Barmar Sep 15 '22 at 21:22
  • 5
    `word_check.reverse()` reverses the list in place and returns `None`. Use `reversed(word_check)` – Barmar Sep 15 '22 at 21:22
  • You can also check if string is palindrome with slicing `word == word[::-1]` where `word[::-1]` means reversing the string. – GodWin1100 Sep 15 '22 at 21:40

2 Answers2

1

Your problem is on this line:

if word_check == word_check.reverse():

You're expecting word_check.reverse() to return the reverse of word_check, but in fact it reverses the parts of word_check in place (i.e. it changes word_check itself, without creating something new). And once it's done, it returns None.

Two ways of doing what you expected:

if word_check == list(reversed(word_check)):

(Note: the list() is needed here to take what reversed() returns and turn it back into a list. After all, word_check is a list, not a reversed type object that allows you to iterate over the data in reverse)

Or:

if word_check == word_check[::-1]

In this case, either is fine. The first example could deal with any object that implements a __reversed__() method, or that supports Python's sequence protocol. You could define your own class that has a concept of being 'reversed' and allows comparison with itself, and this logic would remain the same.

The second example only works for objects that allow indexing with a slice. But a list (or a string) does, so it works here.

The first part of your code effectively does the same as this:

word = input("Input a word: ")
word_check = list(word)

After this, if you enter test, word_check == ['t', 'e', 's', 't'].

But you don't even need to do that with the second solution, so:

# the simplest solution:
word = input("Input a word: ")
if word == word[::-1]:
    print("The word is a palindrome")
else:
    print("The word is not a palindrome")

# if you do actually want to use a list for some reason:
word_check = list(word)
if word_check == list(reversed(word_check)):
    print("Yep, definitely a palindrome")
else:
    print("Nope, definitely not a palindrome")

Here, word itself (the string) is reversed with word[::-1] - since you can index a string with a slice, this works and the resulting string is the same string with its characters in reverse order. So:

word = 'abcd'
print(word[::-1])  # prints `dcba`

A good explanation of slicing is here: Understanding slicing

In case anyone is wondering how the methods compare in performance:

from timeit import timeit


def is_palindrome0(s):
    # simple slice
    return s == s[::-1]


def is_palindrome1(s):
    # reassemble a string from the result of reversed
    return s == "".join(reversed(s))


def is_palindrome2(s):
    # assemble a list from the result of reversed, compare to the list of s
    return list(s) == list(reversed(s))


def is_palindrome3(s):
    # as the previous, but tuples instead
    return tuple(s) == tuple(reversed(s))


print(timeit(lambda: is_palindrome0('abcdedbcaabcdedbca'), number=10000000))
print(timeit(lambda: is_palindrome1('abcdedbcaabcdedbca'), number=10000000))
print(timeit(lambda: is_palindrome2('abcdedbcaabcdedbca'), number=10000000))
print(timeit(lambda: is_palindrome3('abcdedbcaabcdedbca'), number=10000000))

Result (on my machine):

1.6170584000001327
4.881220600000233
5.382383899999695
5.094953499999974
Grismar
  • 27,561
  • 4
  • 31
  • 54
0

Use reversed instead, or slice notation with a step of -1:

#!/usr/bin/env python

def is_palindrome(s):
    return s == "".join(reversed(s))

def is_palindrome_alternative(s):
    return s == s[::-1]

print(is_palindrome("mercy")) # False
print(is_palindrome("hannah")) # True

print(is_palindrome_alternative("starfish")) # False
print(is_palindrome_alternative("".join(["a", "nut", "for", "a", "jar", "of", "tuna"]))) # True
kwiknik
  • 570
  • 3
  • 7