Classes and Objects in Python
Defining classes, creating instances, and understanding __init__ and self.
2 min read
A class is a blueprint for creating objects that bundle data and behavior together. Python's syntax for this is compact once the two special pieces — __init__ and self — click.
Defining a class
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
def bark(self):
return f"{self.name} says woof!"__init__ is the constructor — Python calls it automatically when you create a new instance, and it's where you set up the object's initial state. self refers to the specific instance being worked on; every method takes it as the first parameter, though you never pass it explicitly when calling.
Creating instances
my_dog = Dog("Rex", "Labrador")
your_dog = Dog("Bella", "Poodle")
print(my_dog.name) # Rex
print(my_dog.bark()) # Rex says woof!
print(your_dog.bark()) # Bella says woof!Each call to Dog(...) creates a separate instance with its own name and breed. my_dog and your_dog share the same class (and therefore the same bark method), but hold independent data.
Why self matters
When you call my_dog.bark(), Python translates that behind the scenes into Dog.bark(my_dog) — self inside the method is my_dog. That's how self.name inside bark() knows to look up my_dog's name specifically rather than some shared value. Forgetting self as the first parameter in a method definition is a common early mistake, and it produces a TypeError complaining about the wrong number of arguments the moment you call the method.
Instance attributes vs. class attributes
Attributes set on self inside __init__ (or any method) belong to that specific instance. Attributes defined directly in the class body are shared across every instance unless overridden:
class Dog:
species = "Canis familiaris" # class attribute -- shared
def __init__(self, name):
self.name = name # instance attribute -- per object
print(Dog("Rex").species) # Canis familiaris
print(Dog("Bella").species) # Canis familiarisUse a class attribute for values genuinely shared by every instance (like a constant), and instance attributes for anything that varies object to object.
Methods can update instance state
class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
c = Counter()
c.increment()
c.increment()
print(c.count) # 2This is the core idea behind object-oriented Python: bundle related data (count) and the behavior that changes it (increment) into one unit, instead of passing a plain number around between separate functions. The next lessons build on this with inheritance and Python's special "dunder" methods.
Test what you just learned
4 quick questions. Get all of them right to unlock the next lesson.
You can take the quiz without an account — logging in just lets your result count toward your progress.