1

version 1

def add_author(authors_books, current_books=None):
  if current_books is None:
    current_books = []

  current_books.extend(authors_books)
  return current_books

version 2

def add_author(authors_books):
  current_books = []
  current_books.extend(authors_books)
  return current_books

In version 1 why would you use "current_books = None" and the following "if" statement if you could get the same outcome using the function in version 2?

Is there certain use cases where you would put a parameter as = to None?

Gojilla
  • 81
  • 1
  • 7
  • When `add_author` is called for the second time, we might not want to initialise `current_books` to empty list, maybe? – Austin Mar 29 '20 at 14:37

1 Answers1

1

For example when writing a recursive function that has to pass down something mutable like a list. Toy example:

def foo(collected=None, level=0, max_depth=3):
    if collected is None: # first call!
        collected = []

    collected.append(level)    
    print(collected)

    if level < max_depth:
        foo(collected, level + 1, max_depth)

foo()

# output:
# [0]
# [0, 1]
# [0, 1, 2]
# [0, 1, 2, 3]

A default argument for collected is used such that the first caller does not have to supply collected=[].

None is used instead of [] as the default value such that mutations to collected are not preserved over calls (the Python mutable default argument gotcha).

def foo(collected=[], level=0, max_depth=3):
    collected.append(level)    
    print(collected)

    if level < max_depth:
        foo(collected, level + 1, max_depth)

foo()

# output:
# [0]
# [0, 1]
# [0, 1, 2]
# [0, 1, 2, 3]

foo()

# output:    
# [0, 1, 2, 3, 0]
# [0, 1, 2, 3, 0, 1]
# [0, 1, 2, 3, 0, 1, 2]
# [0, 1, 2, 3, 0, 1, 2, 3]
actual_panda
  • 1,178
  • 9
  • 27