Python Class Starter
class · object · self · attributes · methods · calculator · small battle project
What A Class Solves
class
The blueprint. It describes what data and methods this kind of object should have.
object
One real thing created from a class. hero and enemy can both be Player objects.
__init__
The setup method. Python runs it when you create a new object.
self
The current object. self.hp means this object's hp.
attribute
Data stored inside an object, such as hero.hp or bag.items.
method
A function that belongs to an object, such as hero.take_damage(5).
First Classes: Student and Calculator
Run this first
class Student: def __init__(self, name, energy): self.name = name self.energy = energy def study(self): self.energy -= 10 return f"{self.name} studied. Energy: {self.energy}" def rest(self): self.energy += 20 return f"{self.name} rested. Energy: {self.energy}"student = Student("Mia", 80)print(student.name)print(student.energy)print(student.study())print(student.rest())print(student.energy)Trace the object state
student = Student("Mia", 80)# After __init__:# student.name -> "Mia"# student.energy -> 80student.study()# After study:# student.name -> "Mia"# student.energy -> 70student.rest()# After rest:# student.name -> "Mia"# student.energy -> 90Calculator methods: add, subtract, multiply, divide
class Calculator: def __init__(self, start): self.value = start def add(self, number): self.value += number return self.value def subtract(self, number): self.value -= number return self.value def multiply(self, number): self.value *= number return self.value def divide(self, number): if number == 0: return "Cannot divide by zero" self.value /= number return self.valuecalc = Calculator(10)print(calc.add(5)) # 15print(calc.subtract(3)) # 12print(calc.multiply(2)) # 24print(calc.divide(4)) # 6.0print(calc.divide(0)) # Cannot divide by zeroprint(calc.value) # 6.0Trace calculator.value
calc = Calculator(10)# After __init__:# calc.value -> 10calc.add(5)# calc.value -> 15calc.subtract(3)# calc.value -> 12calc.multiply(2)# calc.value -> 24calc.divide(4)# calc.value -> 6.0calc.divide(0)# calc.value -> still 6.0Mini Project: Class Arena
Students complete a tiny battle simulator. The point is not game design; the point is that Player owns hp and attack behavior, Inventory owns item behavior, and GameStats owns the counters.
class_arena.py
class Player: def __init__(self, name, hp, attack_power): # TODO 1: Store the player's starting data. # Input: # name - a string, for example "Nova" # hp - an integer, for example 30 # attack_power - an integer, for example 7 # Output: # No return value. # Task: # Create these attributes: # self.name # self.max_hp # self.hp # self.attack_power pass def is_alive(self): # TODO 2: Check whether this player is still alive. # Input: # No parameters besides self. # Output: # True if self.hp is greater than 0. # False otherwise. return False def take_damage(self, amount): # TODO 3: Reduce hp. # Input: # amount - an integer damage value. # Output: # No return value. # Task: # Subtract amount from self.hp. # If hp becomes negative, set it back to 0. pass def heal(self, amount): # TODO 4: Restore hp. # Input: # amount - an integer healing value. # Output: # No return value. # Task: # Add amount to self.hp. # If hp becomes greater than self.max_hp, set it back to self.max_hp. pass def attack_target(self, target): # TODO 5: Attack another Player object. # Input: # target - another Player object. # Output: # No return value. # Task: # Call target.take_damage(self.attack_power). pass def status(self): # TODO 6: Return a readable status string. # Input: # No parameters besides self. # Output: # A string. # Example: # "Nova: 24/30 HP, ATK 7" return ""class Inventory: def __init__(self): # TODO 7: Create an empty item list. # Input: # No parameters besides self. # Output: # No return value. # Task: # Create self.items as an empty list. pass def add(self, item): # TODO 8: Add one item to the inventory. # Input: # item - a string, for example "potion" # Output: # No return value. pass def has(self, item): # TODO 9: Check whether an item exists. # Input: # item - a string. # Output: # True if item is inside self.items. # False otherwise. return False def remove(self, item): # TODO 10: Remove one item if it exists. # Input: # item - a string. # Output: # True if an item was removed. # False if the item was not found. return False def summary(self): # This one is already done. if len(self.items) == 0: return "Bag: empty" return "Bag: " + ", ".join(self.items)class GameStats: def __init__(self): # This one is already done. self.rounds = 0 self.actions = 0 def record_round(self): # This one is already done. self.rounds += 1 def record_action(self): # This one is already done. self.actions += 1 def result(self, hero, enemy): # This one is already done. if hero.is_alive(): winner = hero.name else: winner = enemy.name return f"Winner: {winner} | Rounds: {self.rounds} | Actions: {self.actions}"def play_demo(): hero = Player("Nova", hp=30, attack_power=7) enemy = Player("Slime", hp=25, attack_power=8) bag = Inventory() stats = GameStats() if hero.status() == "": print("Template loaded. Start with TODO 1-6 inside Player.") return if not hasattr(bag, "items"): print("Player is ready. Next finish TODO 7-10 inside Inventory.") return bag.add("potion") print(hero.status()) print(enemy.status()) print(bag.summary()) while hero.is_alive() and enemy.is_alive(): stats.record_round() print() print(f"Round {stats.rounds}") hero.attack_target(enemy) stats.record_action() print("Hero attacks.") print(enemy.status()) if not enemy.is_alive(): break enemy.attack_target(hero) stats.record_action() print("Enemy attacks.") print(hero.status()) if hero.hp <= 12 and bag.has("potion"): bag.remove("potion") hero.heal(10) stats.record_action() print("Hero uses potion.") print(hero.status()) print(bag.summary()) print() print(stats.result(hero, enemy))if __name__ == "__main__": play_demo()Quick smoke test
python3 class_arena.py# If the program is working, you should see:# - Nova and Slime status lines# - Round 1, Round 2, ...# - HP going down after attacks# - potion used when Nova is low# - a final Winner linePractice Ladder
Trace an object
Write down how self.energy changes after each method call.
Input
student = Student("Mia", 80)student.study()student.rest()Expected Output
student.name == "Mia"student.energy == 90Fix a missing self bug
Explain why name = name does not create hero.name, then fix the code.
Input
class Player: def __init__(self, name, hp): name = name hp = hphero = Player("Nova", 30)print(hero.name)Expected Output
NovaBuild a Rectangle class
Create __init__, area, and perimeter.
Input
box = Rectangle(3, 5)print(box.area())print(box.perimeter())Expected Output
1516Build a BankAccount class
withdraw should return False when there is not enough money.
Input
account = BankAccount("Mia", 100)print(account.withdraw(30))print(account.balance)print(account.withdraw(1000))Expected Output
True70FalseFinish Player.take_damage
Damage should never make hp negative.
Input
hero = Player("Nova", 30, 7)hero.take_damage(40)print(hero.hp)Expected Output
0Finish Player.heal
Healing should never go above max_hp.
Input
hero = Player("Nova", 30, 7)hero.take_damage(20)hero.heal(99)print(hero.hp)Expected Output
30Use a list attribute
Implement items as self.items, not as a local variable.
Input
bag = Inventory()bag.add("potion")bag.add("key")print(bag.has("key"))print(bag.summary())Expected Output
TrueBag: potion, keyRemove exactly one item
remove should delete one matching item and return True.
Input
bag = Inventory()bag.add("potion")bag.add("potion")print(bag.remove("potion"))print(bag.summary())Expected Output
TrueBag: potionLoop over objects
Use a for loop and player.is_alive() to count how many players are alive.
Input
players = [Player("Nova", 30, 7), Player("Slime", 0, 4)]# Count alive players.Expected Output
1Add a level_up method
Add level_up so max_hp increases by 5 and attack_power increases by 2.
Input
hero = Player("Nova", 30, 7)hero.level_up()print(hero.max_hp)print(hero.attack_power)Expected Output
359Build Calculator.__init__
Create self.value and store the starting number inside the object.
Input
calc = Calculator(10)print(calc.value)Expected Output
10Add and subtract
Make add and subtract update self.value and return the new value.
Input
calc = Calculator(10)print(calc.add(5))print(calc.subtract(8))print(calc.value)Expected Output
1577Multiply and divide
Make multiply and divide update self.value and return the new value.
Input
calc = Calculator(6)print(calc.multiply(3))print(calc.divide(2))Expected Output
189.0Protect against dividing by zero
If number is 0, return an error message and do not change self.value.
Input
calc = Calculator(9)print(calc.divide(0))print(calc.value)Expected Output
Cannot divide by zero9Common Bug: Forgetting self
Broken
class Player: def __init__(self, name, hp): name = name hp = hphero = Player("Nova", 30)print(hero.name)Fixed
class Player: def __init__(self, name, hp): self.name = name self.hp = hphero = Player("Nova", 30)print(hero.name)Where to Slow Down
- Do not rush past self. Ask students to say out loud: self means this object.
- Separate local variables from attributes. name disappears after __init__, but self.name stays inside the object.
- Connect every method to a visible state change: hp decreases, hp heals, items are added, items are removed.