Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Passing a list through a recursive function call causes the list to become 'NoneType', why?

I have the following recursive function:

def recurse(y,n):
    if len(y) == n:
        return y
    else:
        return recurse(y.append(1),n)

When I run it:

x=recurse([],10)

I get the following error:

TypeError: object of type 'NoneType' has no len()

It seems that the function gets past the if statement the 1st time around, then it goes into the next level of recursion, and there, y.append(1) is 'NoneType', why is it not: '[1]' as expected? I have thought about this for a while and I can't seem to figure it out. Any insight is appreciated!

like image 984
casandra Avatar asked Feb 15 '14 02:02

casandra


People also ask

Why does a recursive function return None?

The OP has a recursive function, in which the recursive calls misses a return . It thus evaluates to None whenever it recurses.

What happens when a function is called recursively?

Recursive function: A function is recursive if the function, in order to compute its result, ends up "calling itself".

Why is Python not good for recursion?

This is because Python has a function call overhead where the interpreter does dynamic type checking of function arguments done before and after the function call, which results in additional runtime latency.

What will happen if there is no stopping condition in recursive function?

Your program will just keep on running and never make progress. In other languages, infinite loops are allowed to be optimized away by the compiler.


3 Answers

The problem is here:

y.append(1)

The append() method returns None, so you can't pass its result for building the output list (you'd have to first append to the list and then pass it, as shown in other answers). Try this instead:

def recurse(y, n):
    if len(y) == n:
        return y
    else:
        return recurse(y + [1], n)

The above solution is more in line with a functional programming style. Using append adds an element to an existing list - which will mutate a function parameter, in general not a very good idea. On the other hand y + [1] creates a new list each time, leaving the parameter untouched. Proponents of functional programming will tell you that's a Good Thing.

like image 150
Óscar López Avatar answered Oct 15 '22 08:10

Óscar López


list.append() calls the append method on a list, and while it modifies the list, it returns None.

So it does not return the list.

You want something like:

def recurse(y,n):
    if len(y) == n:
        return y
    else:
        y.append(1)
        return recurse(y,n) # explicitly pass the list itself
like image 30
Totem Avatar answered Oct 15 '22 08:10

Totem


y.append operates on y in place and returns None

like image 3
Rob Falck Avatar answered Oct 15 '22 07:10

Rob Falck