Operator Overloading
Learn about the concept of operator overloading and how it is applied in Python using a practical example.
We'll cover the following...
Overview
Python’s operators, +
, /
, -
, *
, and so on, are implemented by special methods on classes. We can apply Python operators more widely than the built-in numbers and collection types. Doing this can be called overloading the operators: letting them work with more than the built-in types.
Looking back at the the collections.abc
module section, we dropped a hint about how Python connects some built-in features with our classes. When we look at the collections.abc
.Collection
class, it is the abstract base class for all Sized
, Iterable
, Containers
; it requires three methods that enable two built-in functions and one built-in operator:
-
The
__len__()
method is used by the built-inlen()
function. -
The
__iter__()
method is used by the built-initer()
function, which means it’s used by the for statement. -
The
__contains__()
method is used by the built-inin
operator. This operator is implemented by methods of built-in classes.
It’s not wrong to imagine the built-in len()
function has this definition:
def len(object: Sized) -> int:return object.__len__()
When we ask for len(x)
, it’s doing the same thing as x.__len__()
, but is shorter, easier to read, and easier to remember. Similarly, iter(y)
is effectively y.__iter__()
. And an expression like z
in S
is evaluated as if it was S.__contains__(z)
.
And yes, with a few exceptions, all of Python works this way. We write pleasant, easy-to-read expressions that are transformed into special methods. The only exceptions are the logic operations: and, or, not, and if-else. These don’t map directly to special method definitions.
Example
Because almost all of Python relies on special methods, it means we can change their behavior to add features. We can overload the operators with new data types. One prominent example of this is in the pathlib
module:
from pathlib import Pathhome = Path.home()print(home)print(home/ "miniconda3"/ "envs")
What doesn’t vary is that the /
operator is used to connect a Path
object with string objects to create a new Path
object.
Checks for operator overloading
The /
operator is implemented by the __truediv__()
and __rtruediv__()
methods. Python has two places to look for an implementation to make operations commutative. Given an expression of A op B
, where op
is any of the Python operators like __add__
for +
, Python does the following checks for special methods to implement the operator:
-
There’s a special case when
B
is a proper subclass ofA
. In ...