1

I have two problems that are getting errors that I would like to understand. They are likely for similar reasons, hence why I'm grouping them together in this post. I am here to learn how I can understand solving errors like these!

First, one function aims to find even numbers within a list that contains ints, floats, and strings. For some reason, I get an error that says not all of my arguments were able to convert during string formatting. Here is my code:

def recEvenNumbers(lst):
    'return a count of all the even numbers(ints and floats) in the list'
    evens = 0
    
    if lst == []:
        return
    else:
        if type(lst[0])== int or float:
            if ((lst[0]%2*10))==0:
                evens = evens+1
            return recEvenNumbers(lst[1:], evens + 1)

I believe I have this whole function down except this one error. Why is this happening and how can I prevent this in the future?

Another error I am getting is for a different function. Here is the code for that one:

def recMerge(a,b):
    'Merge two strings together recursivly'
    if len(a)==0:
        return
    elif len(b)==0:
        return
    else:
        if type(a) == str:
            if type(b) == str:
                return a[0] + b[0] + recMerge(a[1:], b[1:])

The aim of this function is to merge two strings to create one string that has characters that alternate between each of the two strings. Not really important to my question though, I just want to know why I might be getting a TypeError here. This is what it tells me:

  File "C:/Users/1734/py.py", line 59, in recMerge
    return a[0] + b[0] + recMerge(a[1:], b[1:])
TypeError: can only concatenate str (not "NoneType") to str
>>> 

Why is this happening? I assumed my if type(a) and if type(b) were supposed to handle this. Why can't I use those in this scenario? Or am I just misusing them?

Also, are these two errors related? I know that question may seem strange but if there's a certain element of these questions that I am struggling to understand, I would like to pinpoint what it is and why I am misunderstanding it.

Thanks for your time!

moss icon
  • 21
  • 3
  • Your first function doesn't do any string formatting, so the error must be in the caller of the function, not the function itself. You need to share the actual error message for that one. – Samwise Oct 28 '21 at 21:30
  • 1
    This doesnt do what you think it does `if type(lst[0])== int or float` its a common misconseption in new python programers. Instead you proabably want `if type(lst[0])== int or type(lst[0]) == float`, althought you would be much better to use `if isinstance(lst[0], int) or isinstance(list[0], float)` – Chris Doyle Oct 28 '21 at 21:30
  • First one is says index out of range. Should have stated that, looking back on it – moss icon Oct 28 '21 at 21:46

4 Answers4

3

You've committed one of the classic blunders. This statement does not do what you think it does:

        if type(lst[0])== int or float:

This is parsed by Python as:

        if (type(lst[0])== int) or (float):

And since "float" is always true, you will always take the if here. And when lst[0] is a string, the '%' operator is the string formatting operator. You want:

        if type(lst[0]) in (int, float):

or even

        if isinstance(lst[0],int) or isinstance(lst[0],float):
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
0

The problem with your second function is that it returns None rather than an empty string for the base case where the input is empty. Since your recursion works by adding onto the result of the recursive call, the very last recursive call must be something you can add to.

def recMerge(a: str, b: str) -> str:
    """Merge two strings together recursively.  If the strings are of
    unequal length, the remainder of the longer string is dropped."""
    # Type check (not necessary if you type-annotate and mypy your code!)
    if not isinstance(a, str) or not isinstance(b, str):
        raise TypeError("both parameters must be strings!")

    # Base case: if one param is empty, there's nothing to merge, so return ""
    if not a or not b:
        return ""

    # Recurse with a smaller slice of both parameters.
    return a[0] + b[0] + recMerge(a[1:], b[1:])
Samwise
  • 68,105
  • 3
  • 30
  • 44
0

I know everyone else is commenting your first problem, but it works if you work it right. That said, you should handle the string first and add evens as a None parameter to check on instance for the first pass.

Here's a working function:

def recEvenNumbers(lst, evens = None):
    'return a count of all the even numbers(ints and floats) in the list'
    if evens is None:
        evens = [0]

    if lst:
        # To keep things organized, extract first item
        # into variable and the rest into a smaller list with
        # star selection
        item, *lst = lst

        # Check for string first
        # Pass rest of process if detected.
        if type(item) == str:
            pass
        # Continue as you were before
        elif type(item) == int or float:
            if item % 2 * 10 == 0:
                evens[0] += 1

        # Recurse with appropriate params.
        return recEvenNumbers(lst, evens)
    # Return result.
    return evens[0]

Run the function:

test_list = [1, 2.2, 4, "string"]
recEvenNumbers(test_list)

Output:

1

Part 2:

# Function with commentary.
def recMerge(a, b):
    'Merge two strings together recursivly'
    # Check types
    if type(a) == type(b) == str:
        # Run until b is empty.
        if len(b) > 0:
            # Deconstructing into single and rest of items with asterisk.
            aa, *a_rest = a
            bb, *b_rest = b
            # New `a` value that prepends the rest of a in
            # front of the concatenation of the current a and b characters.
            # Since a_rest is a list, we should "collect" the items back into
            # a proper string format.
            a = "".join(a_rest) + aa + bb
            # Return the new a with another concatenated list for the
            # remaining b items.
            return recMerge(a, "".join(b_rest))
    # Return a.  Ensure that it is a string.
    return "".join(a)

Run test case:

A = "abc"
B = "def"
recMerge(A, B)

Output:

'adbecf'
Mark Moretto
  • 2,344
  • 2
  • 15
  • 21
0

here is my working code.


def recEvenNumbers(lst):
    'return a count of all the even numbers(ints and floats) in the list'
    evens = 0
    if lst == []:
        return 0
    
    elif type(lst[0]) == int or type(lst[0]) == float:
        if ((lst[0]%2))==0:
            evens = evens+1

    return recEvenNumbers(lst[1:]) + evens

    
   
def recMerge(a,b):
    'Merge two strings together recursivly'
    if type(a) != str or type(b) != str:
        return None
        #recMerge ((a[1:]), (b[1:]))

    
    if a == "":
        return b
    elif b == "":
        return a
    else:
        return  a[0] + b[0] + recMerge(a[1:], b[1:])

       

moss icon
  • 21
  • 3