Classes, Objects & Blueprints
Instantiate custom types, bind instance attributes, and define state-modifying behavior.
A Class Is a Blueprint; an Object Is What Gets Built
class ServerConfig: pass defines a blueprint. config = ServerConfig() builds one concrete object from it — an instance. In Python, this isn't just a convenient mental model: classes themselves are objects too, instances of the built-in type metaclass.
Every object carries its own __dict__ — a namespace of the attributes that belong to it specifically — while the class carries a separate __dict__ of attributes and methods shared across every instance.
config['host'] = 'db1'
def __init__(self, host): ...
A class is like an architect's blueprint for a house: the blueprint itself isn't livable, but every house built from it (each instance) has its own address, its own furniture (instance attributes), while sharing the same floor plan (class attributes and methods).
Inspecting Types and Class Objects
Run the snippet below to see how an instance, its class, and the metaclass all relate:
class ServerConfig:
pass
# Creating an instance
config = ServerConfig()
print("Instance type:", type(config))
print("Class type (metaclass):", type(ServerConfig))
print("Is instance of ServerConfig:", isinstance(config, ServerConfig))
print("Is ServerConfig instance of type:", isinstance(ServerConfig, type))Every class is an instance of type — type(MyClass) returns <class 'type'>.
Both instances and classes carry their own __dict__ — the actual namespace attribute lookup searches.
Confirms an object belongs to a class (or any of its parents) without depending on how it was constructed.
Lets an attribute-style read (rect.area) actually run a method under the hood.
How obj.name Actually Resolves
Click through the three lookup steps Python performs for pool1.driver:
Python first looks in the instance's own __dict__. If the attribute is found here, the search stops immediately — this is why setting pool1.driver = 'x' masks the class attribute.
Shared State vs Per-Object State vs Dynamic Access
Every attribute falls into one of these categories — knowing which one avoids the classic shared-mutable-default trap.
Instance attributes
self.host = hostAssigned inside __init__ (or any method) — lives in that one object's __dict__, unique per instance.
pool1.driver = 'x'Assigning directly on an instance creates a new instance attribute that shadows the class attribute of the same name.
Class attributes
driver = "asyncpg" # in class bodyShared by every instance of the class unless an instance attribute of the same name shadows it.
Dynamic access
getattr(obj, name, default)Safe dynamic read — returns default instead of raising AttributeError if the name is missing.
setattr(obj, name, val)Dynamic assignment — equivalent to obj.name = val, useful when the attribute name is a runtime string.
Worked Hands-on Walkthroughs
Progress step-by-step from inspecting types through class/instance namespaces to exposing computed state with @property:
Inspecting Types and Class Objects
config is an instance of ServerConfig, and ServerConfig is an instance of type. Python's object model is fully unified.
class ServerConfig:
pass
# Creating an instance
config = ServerConfig()
print("Instance type:", type(config))
print("Class type (metaclass):", type(ServerConfig))
print("Is instance of ServerConfig:", isinstance(config, ServerConfig))
print("Is ServerConfig instance of type:", isinstance(ServerConfig, type))config is an instance of ServerConfig, and ServerConfig is an instance of type. Python's object model is fully unified.
Class vs Instance Attributes & Namespace Inspection
Assigning pool1.driver creates an entry in pool1.__dict__, masking the class attribute for pool1 without mutating DatabasePool.driver for pool2.
class DatabasePool:
driver = "asyncpg" # Shared Class Attribute
def __init__(self, host, port):
self.host = host # Instance Attribute
self.port = port # Instance Attribute
pool1 = DatabasePool("db1.internal", 5432)
pool2 = DatabasePool("db2.internal", 5432)
# Inspecting namespaces
print("pool1.__dict__:", pool1.__dict__)
print("DatabasePool.driver:", DatabasePool.driver)
# Overriding attribute on a single instance
pool1.driver = "psycopg2" # Writes to pool1.__dict__!
print("pool1.driver:", pool1.driver)
print("pool2.driver:", pool2.driver) # Unaffected!
print("pool1.__dict__ after override:", pool1.__dict__)Assigning pool1.driver creates an entry in pool1.__dict__, masking the class attribute for pool1 without mutating DatabasePool.driver for pool2.
Exposing Computed State via @property
rect.area is accessed without parentheses, yet evaluates dynamically whenever rect.width or rect.height change.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
"""Computed property: dynamically calculated when accessed."""
return self.width * self.height
@property
def perimeter(self):
return 2 * (self.width + self.height)
rect = Rectangle(10, 5)
print("Width:", rect.width)
print("Height:", rect.height)
# Accessed like a standard attribute without parentheses!
print("Area:", rect.area)
print("Perimeter:", rect.perimeter)
# Dynamic recalculation when dimensions change
rect.width = 20
print("Updated Area:", rect.area)rect.area is accessed without parentheses, yet evaluates dynamically whenever rect.width or rect.height change.
Common Traps & How to Avoid Them
Study the mistakes and clean fixes below before designing your own classes:
# Mistyped variable or missing closing parenthesis
result = classes_and_objects__oop__val# Declare and verify variables before execution
val = 10
print("Defined correctly:", val)Beginners frequently encounter typos or forgotten definitions before using an identifier.
# Modifying shared state or unexpected variable shadowing
def update_state(data=[]):
data.append(1)
return datadef update_state(data=None):
if data is None:
data = []
data.append(1)
return dataDefault arguments in Python are evaluated once at function definition time, not at invocation time.
# Opening resources in a tight loop without closing or bounding memory
files = [open(f"log_{i}.txt", "w") for i in range(5000)]for i in range(5):
with open(f"log_{i}.txt", "w") as f:
f.write("Safe")Failing to release system resources leads to process termination under heavy production workloads.
Real-World Systems in Action
See how scripts, microservices, and large distributed domains rely on well-modeled classes:
Local Developer Automation Tool
Individual developers and IT administrators automate everyday repetitive workflows.
A clean standalone script providing fast, local automation with zero dependencies.
class Robot:
def __init__(self, name):
self.name = name
def speak(self):
return f"Greetings, I am {self.name}."
bot = Robot("Atlas")
print(bot.speak())Backend API Service Integration
SaaS platforms run backend microservices processing requests concurrently.
A modular service handler integrating validation and structured responses.
# Service integration layer
def handle_request(payload: dict) -> dict:
return {"status": "success", "processed": True}High-Throughput Cloud Architecture
Enterprise applications model complex domains (Users, Accounts, Subscriptions, Invoices) using cleanly encapsulated class models.
Enterprise applications model complex domains (Users, Accounts, Subscriptions, Invoices) using cleanly encapsulated class models.
# High-resilience production pattern
import time
def process_stream(events: list) -> int:
processed = 0
for event in events:
if event:
processed += 1
return processedKey Points & Concept Review
- Everything in Python is an object, and every class is an instance of the type metaclass.
- Class attributes are defined in the class body and shared; instance attributes are bound to self and unique per object.
- Python resolves obj.x by first inspecting obj.__dict__ before checking type(obj).__dict__ and parent classes.
- Use getattr(obj, name, default) for safe, dynamic attribute retrieval and setattr(obj, name, val) for dynamic assignment.
- Never declare mutable defaults (like [] or {}) at the class body level as they become shared mutable state across instances.
- Use the @property decorator to define calculated or managed attributes accessed with standard dot syntax.
Frequently Asked Questions & Reference Hub
“Everything is an object” sounds abstract until you see it in the REPL — no worries if class-vs-instance attribute scoping feels confusing at first; the moment you accidentally share a mutable default, the distinction becomes permanent.
See exactly how classes are instances of type.
Understand the exact order Python searches for an attribute.
Learn the safe dynamic attribute functions.
See the classic bug from sharing mutable state at class scope.
Learn how @property exposes methods as plain attributes.
Explore Python's built-in introspection attributes.
You've Mastered Classes & Objects!
You understand the object model, attribute lookup order, and computed properties. Now lock in your knowledge with hands-on practice.
Design a class with both shared and per-instance state.
Earn experience points toward your developer rank as soon as you pass.
Bite-sized knowledge check with instant explanations for every question.
Worked example
Model a student once, then stamp out as many as needed — data (name, marks) plus behaviour (grade) live together.
class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks
def grade(self):
return "A" if self.marks >= 80 else "B"
print(Student("Mim", 84).grade())
How it works, step by step
- __init__ runs automatically on creation, filling self.
- self.name / self.marks belong to THIS student.
- Methods read attributes through self — grade() checks this object's marks.
Classes, Objects & Blueprints practice
Create a Circle class. Its __init__ method should save a radius. Add a show_radius method that prints Radius: 4 for a circle with radius 4.
Coding Practice is Locked
Sign in to access the interactive Python editor, write and run code checks against automated tests, use hints, and earn XP.
Practice quiz
Check yourself
15 questions with explanations after submission, so you can correct course as you go.
Classes, Objects & Blueprints quiz
LockedYou must be signed in to take this quiz. Sign in to test your understanding, track your answers, and earn XP.
Lesson incomplete
Not completedCreate an ID or sign in to save lesson completion across devices.