Python by Projects

unit

PET SIMULATOR

Adopt a virtual pet with its OWN name and mood. Feed it, play with it, and watch its stats change.

Each idea comes as a short ladder — simplest first, then one step up, then the real simulator — with a Notice naming the one new thing.

You will learn

  • Write a class whose __init__ method gives each object its own attributes.
  • Make objects such as Pet("Buddy") and read their attributes with a dot.
  • Add methods that read and change an object's attributes.
  • Run a pet simulation with a dictionary, a list and loops.

Lesson 1: Meet Your Pet

A class is a set of instructions for making objects. The __init__ method runs when we make a new pet, and self means this particular pet. The values it stores (self.name, self.hunger, ...) are called attributes.

class Pet:
    def __init__(self, name):
        self.name = name

buddy = Pet("Buddy")
print("Made a new pet!")

Output

Made a new pet!

Notice

Pet("Buddy") makes one object; __init__ runs automatically and stores the name in self.name.

class Pet:
    def __init__(self, name):
        self.name = name
        self.hunger = 5
        self.happiness = 5

buddy = Pet("Buddy")
print("Made a pet with a name, hunger, and happiness.")

Output

Made a pet with a name, hunger, and happiness.

Notice

__init__ can set several attributes — every new pet starts with a name, hunger, and happiness.

Now that a pet exists, a dot reads one of its attributes. Each object carries its OWN attributes.

buddy = Pet("Buddy")
print(buddy.name)
print(buddy.happiness)

Output

Buddy
5

Notice

buddy.happiness reads the happiness attribute of this particular pet.

buddy = Pet("Buddy")
luna = Pet("Luna")
print(buddy.name)
print(luna.name)

Output

Buddy
Luna

Notice

Two pets are two separate objects, each with its own attributes.

buddy = Pet("Buddy")
luna = Pet("Luna")
luna.hunger = 7
print(buddy.hunger)
print(luna.hunger)

Output

5
7

Notice

Changing luna.hunger leaves buddy.hunger at 5 — each object's attributes are independent.

Lesson 2: Teach Your Pet Actions

A method is a function written INSIDE the class. It receives self, so it reads or changes the attributes of this particular pet. (After adding methods to the class, make a NEW pet so it has them.)

class Pet:
    def __init__(self, name):
        self.name = name
        self.hunger = 5
        self.happiness = 5

    def play(self):
        self.happiness = self.happiness + 1

    def pass_time(self):
        self.hunger = self.hunger + 2

buddy = Pet("Buddy")
buddy.play()
buddy.pass_time()
print(buddy.happiness)
print(buddy.hunger)

Output

6
7

Notice

A method is a function inside the class that changes this pet's attributes — play cheers it up, pass_time makes it hungrier.

class Pet:
    def __init__(self, name):
        self.name = name
        self.hunger = 5
        self.happiness = 5

    def play(self):
        self.happiness = self.happiness + 1

    def pass_time(self):
        self.hunger = self.hunger + 2

    def feed(self, amount):
        self.hunger = self.hunger - amount

buddy = Pet("Buddy")
buddy.feed(2)
print(buddy.hunger)

Output

3

Notice

One step up — feed takes a parameter (amount), so you choose how much to feed the pet.

class Pet:
    def __init__(self, name):
        self.name = name
        self.hunger = 5
        self.happiness = 5

    def play(self):
        self.happiness = self.happiness + 1

    def pass_time(self):
        self.hunger = self.hunger + 2

    def feed(self, amount):
        self.hunger = self.hunger - amount
        return self.hunger

buddy = Pet("Buddy")
new_hunger = buddy.feed(2)
print(new_hunger)

Output

3

Notice

One step up — feed now returns the new hunger, so other code can use the result.

class Pet:
    def __init__(self, name):
        self.name = name
        self.hunger = 5
        self.happiness = 5

    def play(self):
        self.happiness = self.happiness + 1

    def pass_time(self):
        self.hunger = self.hunger + 2

    def feed(self, amount):
        self.hunger = self.hunger - amount
        return self.hunger

    def status(self):
        if self.hunger > 6:
            mood = "hungry"
        elif self.hunger < 3:
            mood = "full"
        else:
            mood = "content"
        print(f"{self.name} is {mood}.")

buddy = Pet("Buddy")
buddy.status()

Output

Buddy is content.

Notice

A method can make a decision with if/elif/else — status checks the hunger attribute and reports the pet's mood.

Lesson 3: Run a Pet Day

Put it together: different foods fill a pet by different amounts. A dictionary maps each food to its filling power, and the number becomes feed's amount.

foods = {"apple": 2, "steak": 4}
buddy = Pet("Buddy")
buddy.feed(foods["steak"])
buddy.status()

Output

Buddy is full.

Try it yourself

foods = {"apple": 2, "steak": 4}
name = input("Pet name? ")
food = input("Which food? ")
buddy = Pet(name)
buddy.feed(foods[food])
buddy.status()

Notice

(It reads live input, so it does not run here. Type a food that is in the table.)

Put it together: care for a whole LIST of pets with one loop — each gets a time change and reports its own status.

pets = []
pets.append(Pet("Rex"))
pets.append(Pet("Mochi"))
pets.append(Pet("Ziggy"))
pets.append(Pet("Luna"))
pets.append(Pet("Pip"))

for pet in pets:
    pet.pass_time()
    pet.status()

Output

Rex is hungry.
Mochi is hungry.
Ziggy is hungry.
Luna is hungry.
Pip is hungry.

Try it yourself

pets = []
name = input("Pet name (blank to stop)? ")
while name != "":
    pets.append(Pet(name))
    name = input("Pet name (blank to stop)? ")

for pet in pets:
    pet.pass_time()
    pet.status()

Notice

(It reads live input, so it does not run here.)

Put it together: a while loop plays with Buddy until happiness reaches 10.

buddy = Pet("Buddy")
while buddy.happiness < 10:
    buddy.play()
buddy.status()

Output

Buddy is content.

Try it yourself

name = input("Pet name? ")
buddy = Pet(name)
while buddy.happiness < 10:
    buddy.play()
buddy.status()

Notice

(It reads live input, so it does not run here.)

Attribute names must be spelled exactly. Study the next cell, but do not run it — can you spot the missing letter?

Read the error

buddy.hapiness
AttributeError: 'Pet' object has no attribute 'hapiness'

AttributeError means hapiness does not match happiness, the attribute created in __init__. Fix the spelling and Python finds it again.

Recap

  • A class is a blueprint, and each object made from it carries its own data.
  • __init__ runs when a new object is made, and self means this particular object.
  • A method is a function inside the class that receives self.
  • A pet day puts it all together: a dictionary of foods, a list of pets, and loops that feed, play with and check every pet.
  • A misspelled attribute name raises an AttributeError.

You can now adopt a pet, care for it and watch its mood change.

Go to the exercises (26)

For parents and teachers: report a problem