1

Hi I am trying to practice on recursion question and have been facing an issue

def recurr(container = [], index = 0):
    print(str(container) + " " + str(index))
    if index == 10:
        return recurr

    recurr(container.append(index), index+1)

print(recurr())

This function takes container as list and index as int, now I am trying to append index in container and increment index. But whenever the function is called the value of the container becomes 'None' and I get an error "AttributeError: 'NoneType' object has no attribute 'append'". I am not sure what am I doing wrong so if someone can help me understand that I would be really grateful.

Thank you

TanvirDuggal
  • 37
  • 1
  • 8
  • 1
    You forgot to return the result of recursion, i.e. `return recurr(container.append ...)`. – Selcuk Jun 03 '21 at 01:48
  • Thank you for your response, I added that but the issue still remains – TanvirDuggal Jun 03 '21 at 01:51
  • def recurr(container = [], index = 0): print(str(container) + " " + str(index)) if index == 10: return recurr return recurr(container.append(index), index+1) – TanvirDuggal Jun 03 '21 at 01:51
  • It still throws "AttributeError: 'NoneType' object has no attribute 'append'" – TanvirDuggal Jun 03 '21 at 01:51
  • 1
    ```container.append(...)``` returns ```None``` – ewokx Jun 03 '21 at 01:52
  • Right, use `container + [index]` instead. Also `return recurr` returns the function object. Your code has many issues. It is not clear what you are trying to do. – Selcuk Jun 03 '21 at 01:53
  • 2
    Move the `container,append(...)` into its own statement, above the recursive call. Then you can pass `container` as the first argument. But note that this function will still have problems: The same default value `[]` for container will be used in all calls to `recurr`, so once it has been modified, subsequent calls will pick up the modified list as the default value. So it doesn't really work. Better to use `None` for the default, then set it to a new empty list `[]` inside the function when the value is `None`. – Tom Karzes Jun 03 '21 at 01:54
  • @Selcuk That doesn't append to `container`. It creates a new list, which may not be desirable. – Tom Karzes Jun 03 '21 at 01:55
  • @TomKarzes True, it is not clear what the OP is trying to accomplish. I'm not sure if mutating the method argument in a recursive function is a good idea though. I believe returning a copy of the list is closer to what they wanted to do. – Selcuk Jun 03 '21 at 01:56
  • @Selcuk I am trying to append the value of the index in a list and when the index reaches a certain value it returns the container. TBH I am trying to practices recursive problems. I want to able to set values of the list inside the parenthesis or recursively – TanvirDuggal Jun 03 '21 at 02:17
  • Does this answer your question? [Why does my recursive function return None?](https://stackoverflow.com/questions/17778372/why-does-my-recursive-function-return-none) – VLAZ Nov 03 '22 at 17:11

1 Answers1

1

What Tom Karzes mentioned above is correct. There are a few issues

  1. container.append(index) does not return the container itself. The .append() method appends an item to a container, but does it in place. You need to pull that command up a line, and then pass the container to recurr().

  2. The issue with the default argument being an empty list is also a valid point but probably beyond the scope of this discussion. Just pass in a list explicitly

  3. Your return statement is returning the function when it should probably be returning the container.

  4. The last line needs to return function call return recurr(container, index+1). Without it, you will get all the print statements but the final return value will STILL be None. To understand why, you need to understand a bit about stack frames and function call frames. Each function is calling itself, and when it does, a new stack frame is added, the calling frame can only exit when all downstream frames exit. When the final frame exits, it returns the full container, but it returns it to its caller, which is recurr(container, 9). Of course, if you look at the function, there are NO other return statements, so that frame returns None, and each subsequent frame continues to return None.

Try this:

def recurr(container, index = 0):
    print(str(container) + " " + str(index))
    if index == 10:
        return container
    
    container.append(index)
    return recurr(container, index+1)

x = []
print(recurr(x))

This can be tricky to fully understand so please ask questions and do a little experimentation

myz540
  • 537
  • 4
  • 7