AI for Youth Academy Future Scholars Research Initiative

Year 1 · Week 13

Chapter 13: Methods That Do Things

Last week you built objects with __init__ and self. This week your objects level up: they will do things. You will write methods that let a Pokémon attack, heal, and show its stats. You will also learn __str__ so that print() shows something useful instead of ugly memory addresses.

Session 3: Methods That Do Things

Duration: 60 minutes

Learning Goals

  • Write instance methods that read and modify attributes
  • Use if statements inside methods
  • Add __str__ so print() shows a nice description

Warm-Up Bug Hunt (10 min)

Find the three bugs in this code before touching your keyboard:

class Dog:
    def __init__(name, breed):   # Bug 1
        self.name  = name
        self.breed = breed

    def bark(self):
        print(self.name, 'says: Woof!')

rex = Dog('Rex', 'Labrador')
rex.bark                         # Bug 2
print(rex.colour)                # Bug 3
Show Answers

Bug 1: __init__ must have self as its first parameter. It should be def __init__(self, name, breed):

Bug 2: Calling a method requires parentheses. It should be rex.bark()

Bug 3: colour was never defined as an attribute. It should be rex.breed, or self.colour needs to be added to __init__.

Adding Methods (30 min)

Methods are functions that live inside a class. They always receive self as the first argument so they can access the object's attributes.

class Pokemon:
    def __init__(self, name, hp, damage):
        self.name   = name
        self.hp     = hp
        self.damage = damage

    # Attack another Pokémon
    def attack(self, target):
        target.hp -= self.damage
        print(f'{self.name} attacks {target.name} for {self.damage} damage!')
        if target.hp <= 0:
            print(f'{target.name} fainted!')

    # Heal up to 100 HP
    def heal(self, amount):
        if self.hp + amount > 100:
            self.hp = 100
        else:
            self.hp += amount
        print(f'{self.name} healed! HP is now {self.hp}.')

    # Show current stats
    def show_stats(self):
        print(f'{self.name} — HP: {self.hp} | Damage: {self.damage}')

Try it out:

pikachu    = Pokemon('Pikachu',    100, 20)
charmander = Pokemon('Charmander',  90, 18)

pikachu.show_stats()
pikachu.attack(charmander)
charmander.show_stats()
charmander.heal(30)
charmander.show_stats()

Making print() Look Nice — __str__ (10 min)

Right now, print(pikachu) shows something ugly like <__main__.Pokemon object at 0x7f…>. We can fix that:

    # Add this method inside the Pokemon class
    def __str__(self):
        return f'{self.name} (HP: {self.hp})'

# Now this works beautifully:
print(pikachu)    # Pikachu (HP: 100)

Pair Exercise (10 min)

With your partner, add one more method to Pokemon. Choose one: level_up, use_potion, evolve, or flee. It MUST contain an if statement.

Show Example Answers
def level_up(self):
    self.damage += 5
    if self.hp < 100:
        self.hp = 100
    print(f'{self.name} leveled up! Damage: {self.damage}, HP: {self.hp}')

def flee(self):
    if self.hp > 20:
        print(f"{self.name} doesn't need to flee!")
    else:
        print(f"{self.name} ran away safely!")

Key point: every method has self as the first parameter and contains at least one if statement for conditional logic.

Exit Ticket

  1. What does self refer to inside a method?
  2. Write one sentence in plain English explaining what __str__ does.

Key Vocabulary