Fundamental Functions: 8. Palindrome

I’m having some trouble understanding why my code isn’t giving me the result I want.
I think my logic is correct.

I’d appreciate some feedback.

Screen Link:

My Code:

def is_palindrome(dna):
    for i in range(len(dna)):
        if dna[i] == dna[-1-i]:
            return True
        else:
            return False

What I expected to happen:
return True if the string is a palindrome and False if the string is not a palindrome

What actually happened:

Returned True irrespective of string input

It’s probably because the return is too early.

Consider the second input - AGATA.

With a for loop, it’s worthwhile to review by each iteration:

First iteration:

# input is 'AGATA'

for i in range(len(dna)):       # i is 0
        if dna[i] == dna[-1-i]: # dna[0] = A and dna[-1-0] = A, so they're equal 
            return True         # return because the above condition is true
        else:
            return False

Because the function returns early, the for loop will stop running, and is not able to compare the next iteration which compares ‘G’ == ‘T’; thus, no False is returned.

What you get instead is True.

To fix this, consider how you can make your function return True only if it finishes the whole loop. One way to do this is to return False, if dna[i] is not equal to dna[-1-i]. And when the loop has gone through all iterations, return True outside of the loop.

I’m not sure if I’m explaining things correctly, so feel free to ask for clarifications.

1 Like

Thank you so much for your insight.

I understand the logic behind returning False, if dna[i] is not equal to dna[-1-i]… but I keep wondering what stops the loop from returning False too early as well, as it did with True in my initial code.

1 Like

Hello.

I presume you’ve got something similar to the following right now:

You’re right. It does return early as in not finishing the loop. In this case, it’s okay for it to return False early, even if there are other characters which would not match later on.

This is because with a palindrome, you don’t need to check that every character does not match; even if one character doesn’t match, it will not be a palindrome so we return False immediately.

Consider:

ACDB

In the first iteration, since A is not equal to B, we can safely say it’s a palindrome, so we return False immediately.

There’s no need to check that C equals to D, unless you are interested in making sure all matches are False before you return False. That would require a slight change to the logic and code.

Your explanation is well understood and it makes a lot of sense.

I guess my question is how do I write the for loop to get it to iterate over the whole string based on the if statement and return a value ONLY after it has iterated over all elements of the string?

In other words, how do I make sure the function doesn’t return until all the elements of the string have been iterated over?

One way to do this is to return a boolean variable instead of a raw boolean. Additionally, the return should only happen at the end of the function.

For example:

def is_palindrome(dna):
    # we assume it's a palindrome by default
    result = True
    for i in range(len(dna)):
        if dna[i] != dna[-1-i]:
            result = False
            # you can also add the 'break' keyword to stop the loop, or just let it run again
      
    return result

Another alternative is to count how many times characters do not match. And return the result of comparing the count with 0.

You can also modify the code above to start by assuming it’s False. The logic would be a bit different though.