
REDPIXEL.PL / Shutterstock.com
When it comes toobject-oriented programming languages, Python is a relatively simple one to use to implement classes. Using classes is a key factor inencapsulation,inheritance, andpolymorphism, as well as making your code more modular. Whatever your experience level, understanding classes is extremely useful for helping you write better and cleaner code. In this article, we re going to cover what classes inPythonare, the types of classes, and how to use them.
What Are Classes in Python?
You can think of a class as a template or blueprint which is used to create objects. This is the general term, whereas specific occurrences of objects are known as instances. As such, instances are particular implementations of a class, with their own properties and behavior.
For example, if you want to record the types of cars being sold in a car dealership, you could represent these with the Cars class. Within this class, we could define attributes, such as color, model, speed, year, etc. Multiple instances can then be created to represent specific car types, which can be used with any methods defined in the class. Or, in simpler terms, classes can be considered like a generic house blueprint, where each house that s built from the blueprint would be a class object. At a high level, the behavior of an object is indicated by its methods, while the object s state is represented by its attributes.
Creating and Defining Classes
Creating a class isn t too complicated, and always begins with using the class keyword, followed by the class name with each word capitalized. We usually follow this by defining the __init__() method, which is used to initialize the attributes of any object we create. Class methods and shared attributes can also be defined at this stage. Using our car example, we could create a class as follows:
class Car:
def __init__(self, make, model, year, color):
self.make = make
self.model = model
self.year = year
self.color = color
self.is_running = False
self.speed = 0
def start_engine(self):
if not self.is_running:
self.is_running = True
print("Engine has started.")
else:
print("Engine is already running.")
def stop_engine(self):
if self.is_running:
self.is_running = False
self.speed = 0
print("Engine has stopped.")
else:
print("Engine is already stopped.")
def accelerate(self, increment):
if self.is_running:
self.speed += increment
print(f"Accelerated. Current speed: {self.speed} km/h.")
else:
print("Cannot accelerate. Engine is not running.")
def brake(self, decrement):
if self.is_running:
if self.speed - decrement >= 0:
self.speed -= decrement
print(f"Braked. Current speed: {self.speed} km/h.")
else:
self.speed = 0
print("Car stopped.")
else:
print("Cannot brake. Engine is not running.")
def display_info(self):
print("Car Information:")
print(f"Make: {self.make}")
print(f"Model: {self.model}")
print(f"Year: {self.year}")
print(f"Color: {self.color}")
print(f"Speed: {self.speed} km/h")
status = "Running" if self.is_running else "Stopped"
print(f"Status: {status}")
car1 = Car("Toyota", "Camry", 2022, "Silver")
car2 = Car("Honda", "Accord", 2021, "Black")
car1.start_engine()
car1.accelerate(20)
car1.brake(5)
car1.display_info()
car2.start_engine()
car2.accelerate(30)
car2.brake(10)
car2.stop_engine()
car2.display_info()
First, we define the Car class and the __init__() constructor method. This takes the model , year , make , and color parameters, as well as self , which refers to the created instance. We then assign the parameter values to instance attributes, using the self.[parameter]} syntax. Two extra attributes are also initialized, which represent the state of the engine and the car s overall speed.
We then define some methods inside the class. These check if the engine has started or stopped and provide functionality to increase or decrease the car s speed. We also define the display() method, which prints various attributes of the car instances.
We finish by creating two instances of the class, calling some methods on each, and printing the results, as can be seen in the image.

History-Computer.com
Class Attributes vs. Instance Attributes
We ve briefly gone over what classes, attributes, and instances are, but it s a good idea to distinguish between class and instance attributes. Class attributes are defined within the class, but not within any class methods. They re also shared by all instances we create of the class objects and are accessed by using the class name or any instance. On the other hand, instance attributes are specific to each instance, defined within the __init__() method. Each instance has its own copy of these attributes. Accessing and modification of class and instance attributes are also done through the class or instances themselves respectively. In our previous example, all of the attributes we defined in the car class are instance attributes, because they re defined within the constructor method, and each instance has its own set of these.
To illustrate the difference, consider the following code:
class Car:
total_cars = 0
def __init__(self, make, model):
self.make = make
self.model = model
Car.total_cars += 1
car1 = Car("Toyota", "Camry")
car2 = Car("Honda", "Accord")
print(car1.total_cars)
print(Car.total_cars)
print(car1.make)
print(car1.model)
print(car2.make)
print(car2.model)
We have the same class here, and some instance attributes, make and model . However, we also have the class attribute, total_cars , which tracks the number of created cars. As such, it s defined outside of any class methods. First, we access the class attribute through the car1 instance, and then we access it directly, printing the same result each time. We finish by printing the make and model attributes of both instances, as can be seen in the image.

History-Computer.com
Types of Classes in Python
There are many different kinds of classes in Python. We ve covered standard classes so far, but other common types include abstract, meta, derived, singleton and mixin classes. A brief explanation of these follows.
Abstract classes
Abstract classes are called as such because they can t be directly instantiated, and only provide a blueprint that other classes can use to implement methods andinterfaces. They usually contain abstract methods, which also have no implementation present.
While Python doesn t have an explicit abstract keyword, we can use the ABC class to create abstract classes, along with a decorator to modify the class. For example, we have this code:
from abc import ABC, abstractmethod
class AbstractClass(ABC):
@abstractmethod
def abstract_method(self):
pass
def regular_method(self):
print("This is a regular method.")
class ConcreteClass(AbstractClass):
def abstract_method(self):
print("Implementation of abstract_method.")
obj = ConcreteClass()
obj.abstract_method()
obj.regular_method()
We define the AbstractClass class, and the method abstract_method() . We also define a regular method, regular_Method , and create the ConcreteClass class which contains the implementation for the abstract method. Lastly, an instance of this class is created, both the methods called and the results are printed.

History-Computer.com
Metaclasses
Metaclasses are those which allow you to define the behavior of other classes, usually indicating how they should be created. In this way, metaclasses can be thought of as a class of a class, and they can be rather complex. However, an example of a metaclass was shown in the previous example; the ABC metaclass is used to create and define abstract classes and mark specific methods as abstract.
Derived classes
Derived classes are those which inherit behaviors, methods and properties from another class. They can extend the base class with additional methods or attributes, or even by overriding other methods. It should be noted that the ConcreteClass class in the previous example isn t actually a derived class, since it merely provides a specific implementation for the abstract class. For a simple example, take a look at this code block:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print("The animal makes a sound.")
class Dog(Animal):
def speak(self):
print("The dog barks.")
animal = Animal("Generic Animal")
animal.speak()
dog = Dog("Fido")
dog.speak()
We have the base Animal class, but also the derived Dog class, which contains its own implementation for the speak() method. We create an instance of the base class, assign it to the animal variable, and print the generic message. After this, we create an instance of the derived class, assign it to the dog variable, and call the speak method on this object. This prints a specific message, which we can also see in the console in the image.

History-Computer.com
Singleton classes
Singleton classes are ones which restrict the creation of instances to a single instance. They re mostly used when we want to be able to globally access this instance with different objects when resources need to be shared and when we want to control the intialization. Using global states can be tricky as it can make code less modular, but singleton classes do have their applications. Here s a simple example:
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 is singleton2)
We create the Singleton class and define the __new__() method, which controls the creation of instances. The method checks if the _instance variable is none, upon which it creates an instance using the super().__new__(cls) method. When we create subsequent instances, the existing instance is returned. To finish, we create two instances, singleton1 and singleton2 , and check if they re equivalent. They are shown to be the same through the True output, as we can see in the image.

History-Computer.com
Mixin classes
If we need extra functionality but don t want to use inheritance, mixin classes provide us with another way to achieve this. A mixin class is one that s designed to be mixed with other classes so that it can inherit their properties. In this way, mixin classes add extra features to other classes. Usually, each mixin class provides a specific feature to the class without interrupting the hierarchy, which helps us keep our code modular and customizable. To illustrate, consider the following code:
class FlyMixin:
def fly(self):
print("Flying...")
class SwimMixin:
def swim(self):
print("Swimming...")
class Bird(FlyMixin):
pass
class Duck(FlyMixin, SwimMixin):
pass
bird = Bird()
bird.fly()
duck = Duck()
duck.fly()
duck.swim()
We start by creating the mixin class FlyMixin , making sure to add mixin as a suffix for easy identification. Inside this class, we define the fly() method, which prints the Flying message. We then create the SwimMixin class, and the swim() method, with similar functionality.
After this, the Bird and Duck classes are created. The Bird class incorporates the FlyMixin class, while the Duck class incorporates both mixin classes. We finish by creating instances of both classes and calling the appropriate methods on these instances. The results can be seen in the image.

History-Computer.com
Classes in Python: Wrapping Up
Classes are fundamental to any OOP language, and Python is no exception. Understanding how to use classes helps us to encapsulate our data, utilize inheritance effectively and make our code reusable and customizable. Class attributes differ from instance attributes, in that they re shared among all class instances. There are also many common types of classes. These regular classes, metaclasses, abstract classes, derived classes, singleton classes and mixin classes. These all have their own applications, depending on your project s needs. Gaining an appreciation for all of them will aid you in designing complex programs.