Introduction
A shop needs to know what it has. In this project the data lives inside an object, and the only way to change it is through methods that check the rules, so the stock can never go negative.
This project keeps the data inside an object and makes every change go through a method. The result is a rule, that stock can never go negative, which the rest of the program simply cannot break.
How it works
A stock report
stock = {"pen": 7, "notebook": 4, "eraser": 0}
for item, amount in sorted(stock.items()):
status = "out of stock" if amount == 0 else f"{amount} left"
print(f"{item:<10}{status}")sorted(stock.items()) lists the items alphabetically, and a conditional expression picks the right status text for each one.
Make it yours
- Add prices and a
total_value()method. - Read commands such as
add pen 10orremove pen 3from input (the practice problem does this). - Raise a custom
OutOfStockexception instead of returning False, and catch it in the caller.
Syntax
class Inventory:
def __init__(self):
self.stock = {}
def add(self, item, amount):
self.stock[item] = self.stock.get(item, 0) + amount
Example
class Inventory:
def __init__(self):
self.stock = {}
def add(self, item, amount):
self.stock[item] = self.stock.get(item, 0) + amount
def remove(self, item, amount):
if self.stock.get(item, 0) < amount:
return False
self.stock[item] -= amount
return True
shop = Inventory()
shop.add("pen", 10)
shop.add("notebook", 4)
print(shop.remove("pen", 3))
print(shop.remove("notebook", 9))
print(shop.stock)self.stockis a dictionary from item name to quantity.addusesget(item, 0), so new items start from zero.removerefuses to remove more than is in stock and returns False instead.
Step through shop.remove("pen", 3). The calculation box shows self.stock[item] - amount → 10 - 3 → 7, and the dictionary in the objects panel updates. The second removal asks for 9 notebooks when there are 4, so nothing changes.
Line by line
Inventory()creates an empty stock dictionary.shop.add("pen", 10)and the next line add two items.shop.remove("pen", 3)has enough stock, so it subtracts and returnsTrue.shop.remove("notebook", 9)asks for too many, so it returnsFalseand changes nothing.- The last line prints the dictionary, which shows the stock that remains.
Expected result
True
False
{'pen': 7, 'notebook': 4}
In the real world
Shops, warehouses and online stores all depend on software that protects exactly this rule. When two people buy the last item at the same moment, the check happens inside one place in the system, for the same reason as here.
Common mistakes
- Changing
shop.stockdirectly from outside the class, skipping the checks inremove. - Using
self.stock[item]for an item that does not exist yet, which raisesKeyError;getavoids it. - Forgetting to return a result from
remove, so the caller cannot tell whether it worked.
Best practices
- Keep the data private by convention, and change it only through methods.
- Return a clear result, or raise a specific error.
- Test the boundary, such as removing exactly what is in stock.
Summary
A class wrapped around a dictionary lets methods enforce rules such as "stock never goes below zero". Reports read the data, and every change goes through a method.
Practice
Add a restock_list(minimum) method that returns the items whose quantity is below minimum, sorted by name.
Quick check
Key takeaways
- Let methods be the only way to change the data.
- A method can report success by returning True or False.
- get avoids a KeyError for new items.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.