Chapter 5
Classes and Objects in Python
Object-oriented programming (OOP) is a powerful paradigm in Python that allows us to represent real-world entities as objects. Python achieves this through classes and objects, which provide a structured way to store data and define functions that operate on that data. In this chapter, we will explore all aspects of OOP in Python, including key concepts like abstraction, encapsulation, inheritance, and polymorphism, using classes and objects as the foundation.
What Are Classes and Objects?
Class: A class is a blueprint for creating objects. It defines the attributes (data) and methods (functions) that an object of that class can have.
Object: An object is an instance of a class. It contains specific values for the data defined in the class, and it can use the methods provided by the class.
In Python, everything is an object. Even primitive data types such as integers, strings, and lists are instances of their respective classes.
Example: A Simple Class
Let’s start by defining a class for 2D points:
class Point:
def __init__(self, a=0, b=0):
self.x = a # x-coordinate
self.y = b # y-coordinate
def translate(self, deltax, deltay):
self.x += deltax
self.y += deltay
def odistance(self):
import math
return math.sqrt(self.x**2 + self.y**2) # Distance from origin
The
__init__
method is a constructor that initializes an object of the class.The
translate
method shifts the point by(deltax, deltay)
.The
odistance
method calculates the distance of the point from the origin (0, 0).
Example: Creating an Object
You can create an instance (object) of this class as follows:
p = Point(3, 4) # Creates a Point object at (3, 4)
print(p.odistance()) # Outputs: 5.0 (distance from origin)
Here, p
is an object of the Point
class.
Key Concepts in OOP
1. Encapsulation:
Encapsulation is the process of restricting access to the internal details of an object. In Python, this is often done using private variables (conventionally prefixed with an underscore) and providing access to them through methods.
Example: Encapsulation in Python
class Point:
def __init__(self, a=0, b=0):
self._x = a # Private variable
self._y = b # Private variable
def get_coordinates(self):
return (self._x, self._y)
def set_coordinates(self, a, b):
self._x = a
self._y = b
Here, the coordinates are stored in private variables _x
and _y
. The methods get_coordinates
and set_coordinates
control access to these variables, providing encapsulation.
2. Abstraction:
Abstraction means hiding the implementation details of an object and only exposing the essential functionality. In the Point
class, the user doesn’t need to know how the odistance
method calculates the distance from the origin; they only need to know that calling odistance
will give them the correct result.
3. Inheritance:
Inheritance allows a class to inherit attributes and methods from another class. This helps in code reuse and the creation of hierarchical structures.
class Shape:
def __init__(self, color="red"):
self.color = color
def display(self):
print(f"This shape is {self.color}")
class Circle(Shape):
def __init__(self, radius, color="red"):
super().__init__(color) # Call the constructor of the base class
self.radius = radius
def area(self):
import math
return math.pi * self.radius**2
# Usage
c = Circle(5, "blue")
c.display() # Outputs: This shape is blue
print(c.area()) # Outputs: Area of the circle
Here, Circle
is a subclass of Shape
, inheriting its properties and methods.
4. Polymorphism:
Polymorphism allows objects of different classes to be treated as objects of a common superclass. It is implemented through method overriding, where a method in the child class can have the same name as a method in the parent class but with a different implementation.
class Shape:
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
import math
return math.pi * self.radius**2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
# Polymorphism in action
shapes = [Circle(5), Rectangle(3, 4)]
for shape in shapes:
print(shape.area()) # Will print area of Circle and Rectangle
Special Methods in Python Classes
Python allows classes to have special methods (also known as magic methods) that allow objects to behave in certain ways, like adding two objects together or converting an object to a string.
1. __str__()
Method
__str__()
MethodThe __str__
method allows you to define how an object is represented as a string. It is called automatically when the object is passed to print()
.
class Point:
def __init__(self, a=0, b=0):
self.x = a
self.y = b
def __str__(self):
return f"({self.x}, {self.y})"
# Usage
p = Point(3, 4)
print(p) # Outputs: (3, 4)
2. Operator Overloading with __add__()
__add__()
In Python, you can define how objects of a class behave when used with operators like +
, -
, *
, etc., by implementing special methods like __add__()
for addition.
class Point:
def __init__(self, a=0, b=0):
self.x = a
self.y = b
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
# Usage
p1 = Point(1, 2)
p2 = Point(3, 4)
p3 = p1 + p2 # Uses __add__ method
print(p3) # Outputs: (4, 6)
Example: 2D Point with Polar Coordinates
Let's expand the previous example by using polar coordinates in addition to Cartesian coordinates:
import math
class Point:
def __init__(self, a=0, b=0):
self.r = math.sqrt(a**2 + b**2)
self.theta = math.atan2(b, a) # Handle cases where a = 0
def odistance(self):
return self.r # Distance from origin in polar coordinates
def translate(self, deltax, deltay):
x = self.r * math.cos(self.theta)
y = self.r * math.sin(self.theta)
x += deltax
y += deltay
self.r = math.sqrt(x**2 + y**2)
self.theta = math.atan2(y, x)
def __str__(self):
return f"(r={self.r:.2f}, θ={math.degrees(self.theta):.2f}°)"
# Usage
p = Point(3, 4)
print(p) # Outputs: (r=5.00, θ=53.13°)
p.translate(1, 1)
print(p) # Outputs the new coordinates after translation
In this version:
Point
is represented in polar coordinates, and we translate it in Cartesian coordinates while keeping the interface consistent.The user need not be aware of whether the internal representation is in Cartesian or polar coordinates.
Conclusion
Classes and objects are fundamental to structuring complex programs in Python. They allow you to encapsulate data and functionality, reuse code through inheritance, and implement abstraction and polymorphism to create flexible and maintainable programs. Python’s support for operator overloading, special methods, and exceptions makes classes even more powerful, allowing objects to integrate seamlessly with Python’s language constructs.
In this chapter, we’ve explored how to define classes and objects, implement methods, use special functions, and leverage object-oriented principles to build efficient and readable code.
Last updated