Python Palindromes: an Exhaustive Tutorial
Tags: python, tutorial
Published: 2021-04-16 07:14:52

Let's have some fun with something called "palindromes." Palindromes are words or sentences that are the same forward as they are backwards. Some notable examples are “racecar,” “taco cat,” and “a man, a plan, a canal, Panama.”

There's a lot of guides out there for working with palindromes, but most of them stop at "racecar" because there's no spaces or tricky commas to deal with. This tutorial will go a step further in handling cases like "taco cat" and "a man, a plan, a canal, Panama."

Working with palindromes is likely something you will never do in your professional career as a programmer, but it may show up on a coding interview (because coding interviews can be ridiculous), so it won't hurt to cover them.

# Getting Started

To check if a string is a palindrome, we first need to reverse it. There's actually a very easy way to reverse strings and lists in Python, and that's the list reference `[::-1]`. Check it out in action:

```python
example_string = 'Programming is great!'
print(example_string[::-1]) # Outputs !taerg si gnimmargorP
```
From here, identifying a palindrome is a simple matter of checking if the reversed string equals the regular string. Easy:

```python
is_palindrome = lambda string: string == string[::-1]
print(is_palindrome('racecar')) # Outputs True
print(is_palindrome('hello')) # Outputs False
```
Here we've defined a lambda function called `is_palindrome` that checks that it's `string` input is the same backwards as forwards. Let's see if it works for "taco cat" as well:

```python
print(is_palindrome('taco cat')) # Outputs False
``` 
This returns false because when we reverse "taco cat," we actually get "tac ocat."

# A Better Palindrome Checker
If we want strings like "taco cat" to get picked up as a palindrome, we have to remove spaces. This is where the `replace` function comes in.

## The `replace` Function

Python strings have a function called `replace` that take two inputs, the character to be replaced, and the character to replace it with. For example:

```python
string = 'taco cat'
new_string = string.replace(' ', '')
print(new_string) # tacocat
``` 
With this information, we can now make a palindrome checker that will catch "taco cat" like so:

```python
palindrome_checker = lambda string: string.replace(' ', '') == string[::-1].replace(' ', '')
print(palindrome_checker('taco cat')) # Outputs True
```

This is great, but now we come to our last challenge, "a man, a plan, a canal, Panama." This won't work with our current implementation for two reasons: the capital "P" in "Panama," and all the commas. Take a look:

```python
palindrome = "a man, a plan, a canal, Panama"
print(is_palindrome(palindrome)) # Outputs False
```

The first thing we'll have to do is cast the strings being compared to lowercase. Then, we'll have to get rid of all non alphanumeric characters. For this, we'll use a list comprehension and the `join` function.

# List Comprehensions

List comprehensions are concise ways to create lists in Python. For example, if I wanted a list of the numbers 1 through 100, I simply have to write:

```python
one_through_one_hundred = [i for i in range(1, 101)]
```
For our palindrome checker, what we'll do is use a list comprehension to make a list out of only the alphanumeric characters in the string we're checking. Luckily, Python strings have a built in `isalnum` function that checks if the string contains only letters and numbers:

```python
print("x".isalnum()) # Outputs True
print("3".isalnum()) # Outputs True
print("&".isalnum()) # Outputs False
```
With this function, we can make a list of only the palindrome's alphanumeric characters:

```python
palindrome = "a man, a plan, a canal, Panama"
arr = [char for char in palindrome if char.isalnum()]
print(arr)
# Outputs ['a', 'm', 'a', 'n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'P', 'a', 'n', 'a', 'm', 'a']
```
But wait, we have to make sure the letters are lowercase so that the capital "P" doesn't throw our checker off:

```python
palindrome = "a man, a plan, a canal, Panama"
arr = [char.lower() for char in palindrome if char.isalnum()]
print(arr)
# Outputs ['a', 'm', 'a', 'n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a', 'n', 'a', 'm', 'a']
```

# Putting it All Together

Now, let's combine everything we learned to make a robust palindrome checker. We *_could_* do this with a lambda but it'll get too long to make much sense, let's make a full function. Check this out:

```python
def palindrome_checker(string):
  palindrome_list = [char.lower() for char in string if char.isalnum()]
  return palindrome_list == palindrome_list[::-1]
```
What we've done here is used a list comprehension along with `lower` and `isalnum` to get all the alphanumeric characters in our string into a list, then we return True if the list is the same forward as backwards. Let's test it out:

```python
tests = ["racecar", "taco cat", "a man, a plan, a canal, Panama", "not a palindrome"]
for test in tests:
  print(palindrome_checker(test))
# True
# True
# True
# False
```
The function works perfectly, nicely done!

# Conclusion

This concludes our quick palindrome tutorial. If you like my content, please check out [my blog](https://erikscode.space) where I write multi-part articles on intermediate to advanced level programming topics, or follow me on [Twitter](https://twitter.com/ErikWhiting4). Let me know if you have any questions!