1. Introduction: Functions vs. Methods
In Python programming, the terms function and method are often used interchangeably, but they have a distinct technical difference:
- Function: A reusable block of code defined in the global context that can be called anywhere in a program.
- Method: A function that is defined inside a class. A method is fundamentally a function whose defining characteristic is its encapsulation within a class structure.
In previous modules, we created user-defined methods to implement custom behaviors. In this module, we explore Python's built-in special methods—commonly known as double-underscore methods.
2. Why Do We Need Special Methods?
Standard built-in Python variables come with default behaviors pre-programmed: you can print any basic variable, check its length using len(), or add numbers together using +.
However, when you create your own custom classes, Python does not inherently know how to handle these operations:
- A custom class can contain multiple diverse data attributes.
- Python does not know which attributes should be printed, how to calculate the class's "length," or how two objects of that class should be added together.
- Special methods allow developers to define and customize these default behaviors for their own classes.
The Double-Underscore Syntax (__)
To create a special method, Python requires prefixing and suffixing the method name with two underscores (e.g., __str__, __len__, __add__). These double underscores signal to the Python interpreter that you are redefining or extending a default, built-in system behavior for your class.
3. Example 1: Customizing Object Printing with __str__ (The Book Class)
When you pass an object to print(), Python checks whether a string representation function is available. By defining the __str__ special method, you dictate exactly how your object should be formatted and displayed as text.
Implementation: Formatting Title and Author
Consider a Book class where we want printed books to appear in the format: 'Title' by Author.
class Book:
# Constructor initializing title and author
def __init__(self, title, author):
self.title = title
self.author = author
# Special method defining string representation
def __str__(self):
return f"'{self.title}' by {self.author}"
# Instantiating a book object
book1 = Book("1984", "George Orwell")
# Printing the object directly
print(book1)
Execution Walkthrough
- When
print(book1) executes, Python looks for a string method to represent the object.
- Because
__str__ is defined, Python uses it to present the book's details.
Output:
'1984' by George Orwell
This allows even complex objects to be converted cleanly into text for display and logging.
4. Example 2: Implementing __len__ and __add__ (The Playlist Class)
Special methods can also handle measurements and arithmetic operations. Consider a Playlist class that contains a collection of songs:
__len__: Defines what len(playlist) returns—specifically, the total count of songs inside that playlist.
__add__: Defines what happens when two playlists are combined using the addition operator (+).
The other Parameter in Operator Methods
When overloading the addition operator (+), addition requires two operands. Inside __add__(self, other):
self: Refers to the first playlist object (on the left side of +).
other: Refers to the second playlist object being added (on the right side of +).
class Playlist:
def __init__(self, songs_count):
self.songs_count = songs_count
# Special method to return playlist length
def __len__(self):
return self.songs_count
# Special method to add two playlists together
def __add__(self, other):
# Adding song counts from both playlist objects
return self.songs_count + other.songs_count
# Creating two distinct playlist objects
p1 = Playlist(2) # Playlist 1 with 2 songs
p2 = Playlist(1) # Playlist 2 with 1 song
# 1. Calling len() on p1
print("Length of P1:", len(p1))
# 2. Adding p1 and p2 using '+'
total_songs = p1 + p2
print("Combined Songs:", total_songs)
Execution Walkthrough
- Calling
len(p1): Triggers the custom __len__ method, returning the song count (2).
- Executing
p1 + p2: Triggers __add__, where self.songs_count (2) and other.songs_count (1) are summed together, returning 3.
Output:
Length of P1: 2
Combined Songs: 3
5. Example 3: Combining __add__ and __str__ (The Point Class)
Special methods can work together seamlessly to handle geometric and mathematical data. Consider a 2D Cartesian coordinate Point class with x and y attributes:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
# Formatting point coordinates as a string
def __str__(self):
return f"Point({self.x}, {self.y})"
# Defining coordinate-wise addition for two points
def __add__(self, other):
# Adding x-coordinates and y-coordinates respectively
return Point(self.x + other.x, self.y + other.y)
# Instantiating two points
p1 = Point(2, 3)
p2 = Point(4, 1)
# Adding both points and printing the resulting object
p3 = p1 + p2
print(p3)
Execution Walkthrough
- Executing
p1 + p2: Calls __add__, which adds the respective coordinates (2 + 4 = 6 and 3 + 1 = 4) and returns a new Point(6, 4).
- Executing
print(p3): Automatically calls __str__ on the new point, outputting the formatted coordinate string.
Output:
Point(6, 4)