A class is a blueprint. An object is a real thing built from that blueprint. One "Dog" blueprint can make many dogs — each with its own name, but all able to bark.
This is Object-Oriented Programming (OOP). It lets you bundle data (a dog's name) and behavior (barking) into one neat package. We'll go in two stages: Part A — Basics, then Part B — Advanced.
🟢 Part A — The Basics
1️⃣ Class vs. Object
A class is like a house plan. An object (also called an instance) is an actual house built from it. From one plan you can build a whole street of houses.
class Dog: # the blueprint
pass
rex = Dog() # an object built from the blueprint
fido = Dog() # another, separate object
print(rex) # <__main__.Dog object ...>
2️⃣ The __init__ constructor
__init__ runs automatically the moment you create an object. Use it to set up the starting data each object needs.
class Dog:
def __init__(self, name, age):
self.name = name # store the data
self.age = age
rex = Dog("Rex", 3)
print(rex.name) # Rex
print(rex.age) # 3
3️⃣ The self parameter
self means "this particular object." It keeps each object's data tied to itself, so Rex's name never gets mixed up with Fido's.
💡 Two dogs, two names
rex.name is Rex's, fido.name is Fido's. self is how Python knows which dog you mean.
4️⃣ Attributes vs. Methods
Attributes = the object's data (variables), like self.name.
Methods = the object's actions (functions), like bark().
class Dog:
def __init__(self, name):
self.name = name # attribute (data)
def bark(self): # method (action)
return self.name + " says Woof!"
rex = Dog("Rex")
print(rex.bark()) # Rex says Woof!
🔴 Part B — Advanced
5️⃣ Instance vs. Class variables
An instance variable belongs to one object. A class variable is shared by all objects of that class.
class Dog:
species = "Canis familiaris" # class variable (shared)
def __init__(self, name):
self.name = name # instance variable (unique)
print(Dog("Rex").species) # Canis familiaris
print(Dog("Fido").species) # same for everyone
6️⃣ @classmethod vs. @staticmethod
@classmethod gets the class as cls — great for building objects in a special way.
@staticmethod is just a helper that lives in the class but needs no object.
class Dog:
def __init__(self, name): self.name = name
@classmethod
def puppy(cls): return cls("Baby") # makes a Dog
@staticmethod
def is_dog(sound): return sound == "Woof"
print(Dog.puppy().name) # Baby
print(Dog.is_dog("Woof")) # True
7️⃣ Getters & setters with @property
A property lets you guard an attribute — validate or compute it — while still using simple dog.age syntax.
class Dog:
def __init__(self, age): self._age = age
@property
def age(self): return self._age
@age.setter
def age(self, value):
if value < 0: raise ValueError("Age can't be negative")
self._age = value
d = Dog(3)
d.age = 5 # uses the setter (validates!)
print(d.age) # 5
8️⃣ Inheritance, overriding & super()
A child class inherits a parent's powers, can override a method to change it, and can call the parent with super().
class Animal:
def speak(self): return "..."
class Cat(Animal):
def speak(self): return "Meow" # override
class Puppy(Animal):
def speak(self): return super().speak() + " Woof"
print(Cat().speak()) # Meow
print(Puppy().speak()) # ... Woof
9️⃣ Polymorphism
Different classes can answer the same method call their own way. One loop, many behaviors.
animals = [Cat(), Puppy()]
for a in animals:
print(a.speak()) # each class responds its own way
🔟 Dunder methods & operator overloading
"Dunder" = double underscore. They make your objects behave like built-in types. __str__ controls printing; __add__ makes + work.
@dataclass auto-writes __init__ and __repr__ for data-heavy classes.
Abstract Base Classes force children to implement certain methods.
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
print(Point(1, 2)) # Point(x=1, y=2)
✅ What you learned
Basics: class vs. object, __init__, self, attributes & methods.
Advanced: class vs. instance variables, @classmethod/@staticmethod, @property, inheritance, super(), polymorphism, dunder methods, dataclasses & ABCs.
🎮 Time to Practice!
Build blueprints, then unlock the advanced powers. 📦
🐶
Task 1: Make a Dog Bark
Easy
Write a Dog class with __init__(self, name) and a bark() method returning name + " says Woof!". Create Dog("Rex") and print its bark → Rex says Woof!.
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
return self.name + " says Woof!"
print(Dog("Rex").bark())
🏦
Task 2: A Safe Bank Account
Medium
Write a BankAccount starting at balance 0 with a deposit method that only adds when the amount is positive. Deposit 10, then -99 (ignored), then 20, and print the balance → 30.