0

For the code below, the inventory in add_item gets bound to the function like detailed here:

"Least Astonishment" and the Mutable Default Argument

class Person:
    def __init__(self, name: str, inventory: List[Item] = []):
        self.name = name
        self.inventory = inventory

    def add_item(self, item: Item):
        self.inventory.append(item)

So this is what happens:

Dave.add_item(Book) # has Book
Mary.add_item(Apple) # has Book and Apple

So I understand what's going on now but I want Mary to only have the Apple and I don't know how to fix it so that works.

Reading further down that page, I found that doing self.inventory = [] works but that would prevent me from initializing items to people in their constructors which I would like to keep since my add_item method only adds one thing at a time.

user2415706
  • 932
  • 1
  • 7
  • 19
  • 1
    You *must not* use `[]` as the default here, as every instance that doesn't specify its own inventory will share that one list. Make the default `None` (or something else that is distinct from any useful value of the parameter), and conditionally replace that with `[]` (a *non-shared* empty list) in `.__init__()`. – jasonharper Jun 08 '20 at 23:00
  • so like: ```def __init__(self, name: str, inventory: List[Item] = None): if inventory == None: self.inventory = [] else: self.inventory = inventory ``` @jasonharper? – user2415706 Jun 09 '20 at 01:14
  • 1
    Yes, that's the general idiom for situations like this. – jasonharper Jun 09 '20 at 02:05

1 Answers1

0

Something like this is the answer for anyone looking in the future. Thanks to @jasonharper for the help in comments.

def __init__(self, name: str, inventory: List[Item] = None):         
    if inventory == None: 
        self.inventory = []         
    else: 
        self.inventory = inventory  
user2415706
  • 932
  • 1
  • 7
  • 19