3 More Python Functools Tips

Sarper Makas
ILLUMINATION
Published in
3 min readJan 31, 2024
Microsoft Designer

The Functools module is essential for writing clean, readable, and reusable code in Python. You can read another article called 3 Python Functools Tips if you want to learn about enhancing performance.

In this article, you are going to learn about three more Python Functools tips, which are predefined functions, single dispatch, and total ordering.

Partial or Predefined Functions

Predefined functions mean creating a version of a function by assigning values to its arguments.

from functools import partial

def add(a, b):
print(a + b)

# order of the arguments maters
add2and5 = partial(add, 2, 5) # 2 for a, 5 for b
add2and1 = partial(add, 2, 1) # 2 for a, 1 for b

add2and2()
add2and1()

In this example, theadd function takes two arguments, a and,b and returns the addition of a andb. By using partial function from functools we defined add2and2 , add2and1 function which have predefined a and b values.

The first argument of partial is the function that we want to use for predefinition. Other arguments are the value of the arguments of the function.

Singledispatch | Generics

singledispatchis a decorator that is used for creating versions of a function for different types of data types. This function can behave differently for different data types.

More about decorators:

In order to use singledispatch with a function, we must write versions in which the behavior of the function will change and a version for general usage.

from functools import singledispatch

@singledispatch
def append(obj, x):
print("Unsupported type")

@append.register
def _(obj: list, x: list):
return obj + x

@append.register
def _(obj: set, x: set):
return obj.union(x)

@append.register
def _(obj: str, x: str):
return obj + x

print(append([1, 2, 3], [4, 5]))
print(append({1, 2, 3}, {4, 5}))
print(append("1 2 3", " 4 5"), "\n")

If the type is not supported, the original function is called
append(2, 3)

In this example, the function with singledispatch decorator is the version that we want to run for undefined data types.

Other versions with append.register decorator are versions for specified data types. As you noticed, the decorator starts with the function name that we are working with (append in this case). Also, other functions are named_.

Use type annotations for specifying types.

Total Ordering

total_orderingis used for automatically defining __lt__(), __le__(), __gt__(), __ge__() based on,__eg__() and on of the four methods of a class. These methods are less than, less or equal, greater than, greater or equal, and equal methods (<, <=, >, >=).

from functools import total_ordering

@total_ordering
class Circle:
def __init__(self, radius):
self.radius = radius

def __eq__(self, other):
return self.radius == other.radius

def __lt__(self, other):
return self.radius < other.radius

studentA = Circle(10)
studentB = Circle(12)

# all compressions are working even if we don't define all four
print(studentA == studentB)
print(studentA != studentB)
print(studentA < studentB)
print(studentA <= studentB)
print(studentA > studentB)
print(studentA >= studentB)

In this example, theCircle class has only __eq__ and __lt__ methods but each operation works fine thanks tototal_ordering.

Write less, do more.

--

--