4

The following code tries to create an integer array filled with n times number 1.

import sys

def foo(n):
    if n == 0:
        return []
    else:
        return foo(n-1).append(1)

if __name__ == '__main__':
    foo(5)

Executing this program yields in an error:

AttributeError: 'NoneType' object has no attribute 'append'

What am I doing wrong when creating the array?

5 Answers 5

5

Just look at the following code to understand why you are getting the error,

>>> x = [].append(1)
>>> x is None
True

When you append to a list, the return value is None! So you must do something like this,

def foo(n):
    if n == 0:
        return []
    else:
        return foo(n-1) + [1]

Using + operator is really like calling extend on a list for which the return value is the new list, unlike append.

>>> x = [1] + [1]
>>> x
[1, 1]

NOTE: Obviously for this simple example you should just use,

>>> [1] * 6
[1, 1, 1, 1, 1, 1]

Which is fine for immutable ints but if you are dealing with objects where you don't want references to the same one,

>>> [1 for _ in range(6)]
[1, 1, 1, 1, 1, 1]

But I'm assuming you are writing this to practice recursive solutions and such.

Sign up to request clarification or add additional context in comments.

1 Comment

Funnier way to initialize the list: list(itertools.repeat(1, 6))
4

The problem is in your else-clause. append does not return a new list, but rather adds an element to the list in-place, and then returns None (hence your error). Try this instead,

return foo(n-1) + [1]  # creates a *new* list

2 Comments

Unless there's really a reason to create a new list, this is going to waste a lot of time making a copy of the list at every recursion level. Better to just make it three lines of code and save the hassle; result = foo(n-1) result.append(1) return result
@HenryKeiter Of course there are much better ways to do this (e.g. not using recursion in the first place). I was just illustrating what was wrong with the OP's code.
3

it might be worth noting that python has some nice syntax to cover your usecase:

>>> [1]*5
[1, 1, 1, 1, 1]

2 Comments

...unless you're trying to use this as an opportunity to learn about recursion. :)
Unless you're explicitly trying to learn about recursion, of course :)
1

Your program, slightly changed

import sys

def foo(n):
    if n == 0:
        return []
    else:
        return foo(n-1) + [1]

if __name__ == '__main__':
    print(foo(5))

Prints

[1, 1, 1, 1, 1]

list.append() modifies the list, but doesn't return anything. So recursions of your function that reach that branch actually return nothing or None.

The method I listed appends an element to the list, and then returns the list, so your recursion works just as you had wanted.

6 Comments

I post the answer, then edit in the explanation, refresh in a few seconds.
@Marcin: haters gonna hate... +1 for me.
@Marcin, Downvoting competing answers -- classy.
@jedwards If an answer isn't useful, I downvote it. Feel free to downvote mine if you think describing the actual issue isn't useful.
Certainly then you remove the downvote when the answer was edited to "be helpful", no?
|
-3

append returns None. This is the problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.