📦 Objects & Classes

Bundle data and behavior together — from blueprints to superpowers

← Back to Architecture

🧸 The big idea

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.

class Money: def __init__(self, amt): self.amt = amt def __str__(self): return f"${self.amt}" def __add__(self, other): return Money(self.amt + other.amt) print(Money(5) + Money(3)) # $8

1️⃣1️⃣ Python extras: dataclasses & ABCs

  • @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.