1

How can I remove the multiple returns from my code without ruining the output or having errors?

My code has multiple returns and I want it to have a single return but whenever I try to change it into one return it ruins my code and it doesn't escalate the way I want it.

My Code:

def is_palindrome(s):
    """
    -------------------------------------------------------
    Recursively determines if s is a palindrome. Ignores non-letters and case.
    Use: palindrome = is_palindrome(s)
    -------------------------------------------------------
    Parameters:
        s - a string (str)
    Returns:
        palindrome - True if s is a palindrome, False otherwise (boolean)
    -------------------------------------------------------
    """
    if len(s) <= 1:
        return True
    else:
        if not s[0].isalpha():
            return is_palindrome(s[1:])
        elif not s[-1].isalpha():
            return is_palindrome(s[:-1])
        if s[0].lower() != s[len(s) - 1].lower():
            return False
        else:
            return is_palindrome(s[1:-1])
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
cat
  • 39
  • 3
  • 1
    Why do you want to have a single return? This is only making the code more complicated. – mkrieger1 Jun 07 '21 at 22:04
  • The argument for a single return statement makes for sense for function with nested conditions or loops which can hide the return; but in those cases you should probably refactor the code to reduce the cognitive complexity anyway. For such a simple/short function you should leave your code as it is and spend time on more important things. – Tony Jun 07 '21 at 22:10

3 Answers3

2

If we want "one point of exit" (return) we can save the result into a variable and return it at the end:

def is_palindrome(s):
    """
    -------------------------------------------------------
    Recursively determines if s is a palindrome. Ignores non-letters and case.
    Use: palindrome = is_palindrome(s)
    -------------------------------------------------------
    Parameters:
        s - a string (str)
    Returns:
        palindrome - True if s is a palindrome, False otherwise (boolean)
    -------------------------------------------------------
    """
    if len(s) <= 1:
        res = True
    else:
        if not s[0].isalpha():
            res = is_palindrome(s[1:])
        elif not s[-1].isalpha():
            res = is_palindrome(s[:-1])
        elif s[0].lower() != s[len(s) - 1].lower():
            res = False
        else:
            res = is_palindrome(s[1:-1])
    return res

Note that the second if was modified to elif - this will not change the execution flow!

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
1

Just assign a variable in all your conditional statements, then return that. You also need to change your second if to an elif to not execute if the previous statement did execute:

def is_palindrome(s):
    """
    -------------------------------------------------------
    Recursively determines if s is a palindrome. Ignores non-letters and case.
    Use: palindrome = is_palindrome(s)
    -------------------------------------------------------
    Parameters:
        s - a string (str)
    Returns:
        palindrome - True if s is a palindrome, False otherwise (boolean)
    -------------------------------------------------------
    """
    if len(s) <= 1:
        out = True
    else:
        if not s[0].isalpha():
            out = is_palindrome(s[1:])
        elif not s[-1].isalpha():
            out = is_palindrome(s[:-1])
        elif s[0].lower() != s[len(s) - 1].lower():
            out = False
        else:
            out = is_palindrome(s[1:-1])
    return out
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
David Kaftan
  • 1,974
  • 1
  • 12
  • 18
0

You can reduce your logic to a single long condition, which (though multi-line) is in some ways more readable, making the logic very clear:

def is_palindrome(s):
    return (len(s) <= 1
            or (not s[0].isalpha() and is_palindrome(s[1:])) 
            or (not s[-1].isalpha() and is_palindrome(s[:-1]))
            or (s[0].lower() == s[-1].lower() and is_palindrome(s[1:-1])))

This is just as efficient as your original code due to short-circuiting - conditions are only evaluated if and when they need to be evaluated.

If you strip the string of non-alphabetic characters first, then the recursive part can be made very simple:

def is_palindrome(s):
    """ Determines if string s is a palindrome, ignoring non-alphabetic characters
        and ignoring case """
    return is_palindrome_general([c for c in s.lower() if c.isalpha()])

def is_palindrome_general(s):
    """ Determines if sequence s is a palindrome, treating all types of
        item the same """
    return len(s) <= 1 or (s[0] == s[-1] and is_palindrome_general(s[1:-1]))

(I split this into 2 functions just to avoid unnecessary repetition of the part that strips out the non-alphabetic characters.)

Stuart
  • 9,597
  • 1
  • 21
  • 30