Using None as a Sentinel Help

Exercise, I asked this question here already but didn’t get a response:

Why does using None as a default value for current_order fix this code when we still assign current_order to [] and then append items to it later. Also I noticed something weird when I called print(order1) again after calling update_order() with order2 (right at the end of the broken code).

Broken Code:

def update_order(new_item, current_order=[]):
  if current_order is None:
    current_order = []
  current_order.append(new_item)
  return current_order

order1 = update_order({'item': 'burger', 'cost': '3.50'})
print(order1)
#prints [{'item': 'burger', 'cost': '3.50'}]
order1 = update_order({'item': 'soda', 'cost': '1.50'}, order1)
print(order1)
#prints [{'item': 'burger', 'cost': '3.50'}, {'item': 'soda', 'cost': '1.50'}]
order2 = update_order({'item': 'soda', 'cost': '1.50'})
print(order2)
#prints [{'item': 'burger', 'cost': '3.50'}, {'item': 'soda', 'cost': '1.50'}, {'item': 'soda', 'cost': '1.50'}]
print(order1)
#for some reason prints [{'item': 'burger', 'cost': '3.50'}, {'item': 'soda', 'cost': '1.50'}, {'item': 'soda', 'cost': '1.50'}]

Fixed Code:

def update_order(new_item, current_order=None):
  if current_order is None:
    current_order = []
  current_order.append(new_item)
  return current_order

order1 = update_order({'item': 'burger', 'cost': '3.50'})
print(order1)
#prints [{'item': 'burger', 'cost': '3.50'}]
order1 = update_order({'item': 'soda', 'cost': '1.50'}, order1)
print(order1)
#prints [{'item': 'burger', 'cost': '3.50'}, {'item': 'soda', 'cost': '1.50'}]
order2 = update_order({'item': 'soda', 'cost': '1.50'})
print(order2)
#prints [{'item': 'soda', 'cost': '1.50'}]
print(order1)
#prints [{'item': 'burger', 'cost': '3.50'}, {'item': 'soda', 'cost': '1.50'}]

This is so common, its even in the python gotchas:

https://docs.python-guide.org/writing/gotchas/

When using a mutable data type (like a list), the mutable data type is created once.

2 Likes

Yeah, I got that it’s because None is non mutable, but why does that fix the weirdness since we’re changing the variable in the function regardless of whether it’s mutable or not?

If you use a mutable data type like a list as parameter, the list is created once.

and this condition:

def update_order(new_item, current_order=[]):
  if current_order is None:

evaluate to false, the parameter list is used