Classes are the foundation of object-oriented programming in Python. Once you understand how they work, you can model real-world things in code, reuse logic cleanly, and write programs that are far easier to extend.
Before classes, you might write a function that takes a dog's name and age as arguments every time you need to do something with that dog. With a class, you define the dog once — its data and its behaviors — and then create as many dogs as you need. This tutorial walks you through every piece of that process, step by step.
What Is a Class?
A class is a blueprint. The official Python documentation describes a class as a way to bundle data and functionality together. When you create an instance of a class, you get an object with its own set of data, called attributes, and a set of actions it can perform, called methods.
Think of a class the same way you think about the concept of a car. The concept of "car" describes something that has a make, a model, a year, and the ability to start, accelerate, and brake. Every individual car you drive is a specific instance of that concept — it has its own make, its own color, its own mileage. The class is the concept; the instance is the actual object you work with.
Python is an object-oriented language, which means almost everything in Python is already an object — strings, lists, integers. When you define your own class, you are creating your own custom type with behavior that you control.
Python names classes using PascalCase by convention, where each word in the name starts with a capital letter. You would write BankAccount not bank_account and UserProfile not user_profile. This is a style convention, not a language rule, but following it makes your code immediately readable to other Python developers.
Defining a Class and the __init__ Method
You define a class with the class keyword, a name in PascalCase, and a colon. Everything indented below that line is part of the class body. The most important method you will write inside a class is __init__. Python calls this method automatically every time a new instance of the class is created.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
There is a lot happening in those four lines. The class Dog: line declares the class. def __init__(self, name, age): defines the constructor method. The first parameter, self, is a reference to the instance being created — Python passes it automatically, so you never include it when calling the method. name and age are the values you supply when you create a new Dog object.
Inside __init__, the lines self.name = name and self.age = age create instance attributes. These are pieces of data that live on each individual object. When you write self.name, you are saying "store this value on this specific instance."
To create an instance, you call the class name like a function and pass the required arguments:
my_dog = Dog('Rex', 4)
print(my_dog.name) # Rex
print(my_dog.age) # 4
You do not write Dog.__init__(my_dog, 'Rex', 4). Python handles passing self for you when you create the instance. You only pass the non-self arguments: Dog('Rex', 4).
Build the correct line to create a Dog instance named my_dog with name 'Bella' and age 2:
variable = ClassName(arguments). The class is called like a function. Square brackets are used for indexing, not object creation. The arguments map positionally to the __init__ parameters after self: first name, then age.
Instance Attributes and Methods
Attributes store data. Methods define behavior. A method is simply a function defined inside a class, and like __init__, it always takes self as its first parameter. Through self, a method can read or modify any attribute on the instance.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
return f"{self.name} says: Woof!"
def birthday(self):
self.age += 1
return f"{self.name} is now {self.age}."
my_dog = Dog('Rex', 4)
print(my_dog.bark()) # Rex says: Woof!
print(my_dog.birthday()) # Rex is now 5.
print(my_dog.age) # 5
Notice how bark uses self.name to get the dog's name, and birthday both reads and modifies self.age. Methods that change the state of the object are sometimes called mutators. Methods that only read state and return a value are sometimes called accessors.
You call methods using dot notation: my_dog.bark(). Python automatically passes my_dog as self to the bark method. You do not pass self yourself.
The Dog class below has one bug. Click the line you think is wrong, then hit check.
def bark(name): to def bark(self):. Every instance method must accept self as its first parameter. Without self, Python cannot pass the instance to the method, and line 6 will raise a NameError because self is undefined inside the function body.
Class Attributes vs. Instance Attributes
An instance attribute is set with self inside __init__ and belongs to one specific object. A class attribute is defined directly in the class body, outside any method, and is shared by all instances. Changing a class attribute affects every instance that has not overridden it locally.
class Dog:
species = 'Canis lupus familiaris' # class attribute
def __init__(self, name, age):
self.name = name # instance attribute
self.age = age # instance attribute
rex = Dog('Rex', 4)
bella = Dog('Bella', 2)
print(rex.species) # Canis lupus familiaris
print(bella.species) # Canis lupus familiaris
print(rex.name) # Rex
print(bella.name) # Bella
species is the same for every Dog because it is a class attribute — it is stored on the class itself, not on each instance. name and age are different for each Dog because they are instance attributes set individually at creation time.
- Where defined
- Directly in the class body, outside any method
- Shared?
- Yes — shared across all instances unless overridden on an instance
- Example
species = 'Canis lupus familiaris'
- Where defined
- Inside
__init__usingself.attribute = value - Shared?
- No — each instance has its own independent copy
- Example
self.name = name
- Where defined
- Inside the class body, indented as a function with
selfas first parameter - Shared?
- The method definition is shared, but
selfgives each call access to that instance's own data - Example
def bark(self): return f"{self.name} says: Woof!"
How to Define and Use a Class in Python
Follow these five steps to go from an empty file to a working class with multiple instances and methods.
-
Declare the class
Write
class ClassName:at the top level of your file. Use PascalCase for the name. Everything that belongs to the class will be indented one level below this line. -
Write the __init__ method
Inside the class body, define
def __init__(self, param1, param2):. Useself.attribute = paramfor each piece of data you want to store on the instance.__init__runs once every time a new instance is created. -
Add instance methods
Define additional functions inside the class using
def method_name(self):. Access instance data withself.attribute. Add extra parameters afterselfwhen the method needs input beyond the stored state. -
Create an instance
Outside the class definition, call the class like a function:
my_object = ClassName(arg1, arg2). Python will call__init__for you with those arguments. You can create as many separate instances as you need. -
Call methods on the instance
Use dot notation:
my_object.method_name(). Python passes the instance asselfautomatically. Read attributes withmy_object.attribute_nameor change them through a method.
Inheritance: Building on Existing Classes
Inheritance lets you create a new class that automatically gets all the attributes and methods of an existing class. The existing class is called the parent class or superclass. The new class is called the child class or subclass. You declare inheritance by placing the parent class name in parentheses after the child class name.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
return f"{self.name} says: Woof!"
class ServiceDog(Dog):
def __init__(self, name, age, role):
super().__init__(name, age) # call the parent __init__
self.role = role # add child-specific attribute
def introduce(self):
return (f"I am {self.name}, a {self.role} dog.")
helper = ServiceDog('Buddy', 3, 'guide')
print(helper.bark()) # Buddy says: Woof! (inherited)
print(helper.introduce()) # I am Buddy, a guide dog.
ServiceDog inherits from Dog, so it automatically gets the bark method without you needing to rewrite it. The call to super().__init__(name, age) runs the parent's constructor, which sets up self.name and self.age. Then the child's constructor adds its own attribute, self.role.
"Classes provide a means of bundling data and functionality together." — Python Documentation
If you define __init__ in a child class and forget to call super().__init__(), the parent's attributes will not be initialized. Any method that tries to access self.name or self.age will raise an AttributeError.
Python Learning Summary Points
- A class is a blueprint defined with the
classkeyword. An instance is an individual object created from that blueprint by calling the class like a function. __init__is the constructor method that runs automatically when a new instance is created. Use it to set instance attributes withself.attribute = value.- Every instance method must accept
selfas its first parameter. Python passes the calling instance asselfautomatically — you never pass it yourself. - Class attributes are defined in the class body and shared by all instances. Instance attributes are set with
selfin__init__and are unique to each object. - Inheritance allows a child class to reuse the attributes and methods of a parent class. Use
super().__init__()in the child's__init__to initialize the parent's attributes.
From here, practice by modeling real things you can describe with data and behavior: a bank account with a balance and deposit/withdraw methods, a student with grades and a GPA calculator, a rectangle with width and height and an area method. Classes click fastest when you build them yourself.
Frequently Asked Questions
A class in Python is a blueprint for creating objects. It defines a set of attributes and methods that the objects created from it will have. You define a class with the class keyword followed by a name and a colon.
__init__ is the constructor method in a Python class. It runs automatically when you create a new instance of the class and is used to set the initial state of the object's attributes.
self is a reference to the current instance of the class. It is the first parameter of every instance method and gives the method access to the object's attributes and other methods. The name self is a convention — Python does not require that exact word, but every Python developer uses it.
A class is the blueprint or template. An instance is an individual object created from that blueprint. You can create many separate instances from a single class, each with its own attribute values. Dog is the class; my_dog = Dog('Rex', 4) creates one instance of it.
Inheritance allows one class (the child or subclass) to acquire the attributes and methods of another class (the parent or superclass). You declare it by placing the parent class name in parentheses after the child class name: class ServiceDog(Dog):.
super() returns a proxy object that allows a child class to call methods from its parent class. It is commonly used inside __init__ to run the parent's constructor before adding child-specific setup.
You create an instance by calling the class name as if it were a function, passing any arguments that __init__ requires. For example: dog = Dog('Rex', 3) creates a Dog instance named dog.
A class attribute is defined directly on the class body and is shared by all instances. An instance attribute is set with self inside __init__ and belongs only to that specific instance.
Yes. A Python class can have any number of methods. Each method is a function defined inside the class body with self as its first parameter. Methods can read and modify the instance's attributes.
Yes. Classes build on functions, so you should understand how to define and call functions, and be comfortable with parameters and return values, before tackling classes.