Object-Oriented Programming Basics (Classes and Objects)
Goals for today
- Understand what classes and objects are
- Learn the parts of a class: attributes, methods, __init__, and self
- Create and use multiple objects
- Know the difference between instance attributes and class attributes
Why OOP?
- Think of a "blueprint" (class) to make many "houses" (objects).
- A class bundles data (attributes) and actions (methods) together.
- This makes code easier to organize, reuse, and reason about.
Key ideas (in plain words)
- Class: A blueprint that describes what something is and what it can do.
- Object (or instance): A real thing made from the class blueprint.
- Attribute: A variable that belongs to an object (like name, age).
- Method: A function inside a class that an object can use (like bark, move).
- __init__: A special method that runs when you create an object; it sets initial values.
- self: A name that points to the current object. Inside methods, self lets you access the object's own attributes and methods.
- Class attribute vs instance attribute:
- Instance attribute: Belongs to one object (e.g., this dog's name).
- Class attribute: Shared by all objects of the class (e.g., the species for all dogs).
Code example 1: Your first class and object
# A simple Dog class
class Dog:
def __init__(self, name, age):
# These are instance attributes
self.name = name
self.age = age
# Create an object (an instance) of Dog
buddy = Dog("Buddy", 3)
print(buddy.name) # Buddy
print(buddy.age) # 3Code example 2: Adding methods (actions)
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
print(f"{self.name}: Woof!")
def have_birthday(self):
self.age += 1
def info(self):
return f"{self.name} is {self.age} years old."
buddy = Dog("Buddy", 3)
buddy.bark() # Buddy: Woof!
print(buddy.info()) # Buddy is 3 years old.
buddy.have_birthday()
print(buddy.info()) # Buddy is 4 years old.Code example 3: Many objects, one class
dogs = [
Dog("Buddy", 4),
Dog("Luna", 2),
Dog("Max", 1)
]
for d in dogs:
print(d.info())
d.bark()Code example 4: Class attributes (shared by all)
class Dog:
# Class attribute: the same for all Dog objects
species = "Canis familiaris"
def __init__(self, name, age):
self.name = name # instance attribute
self.age = age # instance attribute
d1 = Dog("Buddy", 4)
d2 = Dog("Luna", 2)
print(Dog.species) # Canis familiaris
print(d1.species) # Canis familiaris
print(d2.species) # Canis familiaris
# Changing the class attribute affects all future lookups (unless overridden on an instance)
Dog.species = "Domestic dog"
print(d1.species) # Domestic dog
print(d2.species) # Domestic dogCommon gotchas
- Forgetting self in method definitions (def bark(self): not def bark():).
- Trying to use attributes before setting them in __init__.
- Calling a method without parentheses (dog.bark vs dog.bark()).
Mini project: Virtual Pet
Build a tiny "Virtual Pet" game using a class. You'll manage your pet's hunger and energy with methods.
What you'll make
A Pet class with:
- name (string)
- hunger (0–10, where 10 = very hungry)
- energy (0–10, where 10 = full of energy)
Methods to feed, play, nap, and show status.
Steps
- Complete the Pet class below by filling in the TODOs.
- Create at least two Pet objects and simulate a day by calling methods.
- Print status after each action to see changes.
- Optional challenge:
- Add a method mood() that returns "happy", "ok", or "grumpy" based on hunger/energy.
- Add a class attribute count to track how many pets exist.
Starter code (fill in the TODOs)
# Virtual Pet
class Pet:
# Optional class attribute to count pets (uncomment if you want the challenge)
# count = 0
def __init__(self, name):
self.name = name
self.hunger = 5 # 0 = full, 10 = very hungry
self.energy = 5 # 0 = exhausted, 10 = full energy
# If using the challenge:
# Pet.count += 1
def feed(self, amount):
"""
Decrease hunger by 'amount' (suggest 1–3). Clamp between 0 and 10.
"""
# TODO: reduce hunger
# Hint: use max(0, value) and min(10, value) to clamp
self.hunger = max(0, self.hunger - amount)
def play(self, minutes):
"""
Playing makes the pet hungrier and uses energy.
For example: every 10 minutes -> hunger +1, energy -1.
"""
steps = minutes // 10
# TODO: increase hunger, decrease energy, clamp 0–10
self.hunger = min(10, self.hunger + steps)
self.energy = max(0, self.energy - steps)
def nap(self, minutes):
"""
Napping restores energy. Maybe it also slightly increases hunger.
For example: every 10 minutes -> energy +1, hunger +0 (or +1 if you want).
"""
steps = minutes // 10
# TODO: increase energy (and optionally hunger), clamp 0–10
self.energy = min(10, self.energy + steps)
# Optional: hunger goes up a little while resting
self.hunger = min(10, self.hunger + steps // 2)
def status(self):
"""
Print a simple status bar for hunger and energy.
"""
hunger_bar = "#" * self.hunger + "-" * (10 - self.hunger)
energy_bar = "#" * self.energy + "-" * (10 - self.energy)
print(f"{self.name} | Hunger: [{hunger_bar}] {self.hunger}/10 Energy: [{energy_bar}] {self.energy}/10")
# Optional challenge
# def mood(self):
# if self.hunger <= 3 and self.energy >= 7:
# return "happy"
# elif self.hunger >= 8 or self.energy <= 2:
# return "grumpy"
# else:
# return "ok"
# Try it out
pet1 = Pet("Pixel")
pet2 = Pet("Noodle")
pet1.status()
pet1.feed(2)
pet1.play(20)
pet1.nap(30)
pet1.status()
pet2.status()
pet2.play(40)
pet2.feed(3)
pet2.status()
# Optional:
# print("Pets created:", Pet.count)
# print(pet1.name, "is", pet1.mood())
# print(pet2.name, "is", pet2.mood())Expected behavior (example)
- After feeding, hunger goes down (toward 0).
- After playing, hunger goes up and energy goes down.
- After napping, energy goes up; hunger might rise a little.
- Status shows the bars changing.
Summary
- A class is a blueprint; an object is a specific thing made from it.
- __init__ sets up new objects; self refers to the current object.
- Attributes store object data; methods define object behavior.
- Instance attributes belong to one object; class attributes are shared by all.
- OOP helps you organize code by putting data and behavior together.