Mastering Python’s Fluent Interface Pattern Made Easy for Effortless Development

Photo by Alexandra Sellick: https://www.pexels.com/photo/green-mountain-and-river-3322315/

Introduction

Using a fluent interface can make your code easier to read. This pattern allows you to connect method calls, as each method returns the object or context. When implemented well, it can create a kind of specialized language for a specific domain.

Let’s see how this works in Python

Implementation in Python

Because in our Python implementation the methods in the class need to return an object of that class we need to import this first:

from typing import Self

In this example we will create a simple Address type:

class Address:
    _street: str = None
    _number: int = None
    _city: str = None
    _country: str = None

    def street(self, street: str) -> Self:
        self._street = street
        return self

    def number(self, number: int) -> Self:
        self._number = number
        return self

    def city(self, city: str) -> Self:
        self._city = city
        return self

    def country(self, country: str) -> Self:
        self._country = country
        return self

    def __str__(self) -> str:
        return f"{self._street} {self._number} in {self._city},{self._country}"

A few notes:

  • There is no explicit constructor
  • Each method, apart from the __str__() method, return Self which is an object of the class Address in our case.This is done so method calls can be chained, as we will see later.
  • The __str__() is a utility to make printing the Address easier.

Testing time

Now we can test our setup:

if __name__ == "__main__":
    address = Address()
    address.street("Middle road").number(50).city("Arcadia").country("Utopia")
    print(address)

A short description:

  1. We create an empty address.
  2. Then, through method chaining, we set its fields
  3. And we print out the address, so we know the fields have been set correctly.

Conclusion

The fluent interface enhances code readability and flexibility. However, it may not always be the best choice. Consider trade-offs, as while it improves readability in some cases, it could lead to unwieldy chains of method calls, increasing complexity.

Leave a Reply

Your email address will not be published. Required fields are marked *