DEV Community

Vinícius Muniz de Melo
Vinícius Muniz de Melo

Posted on

Callable Python

Introduction

Python has a lot of magic methods that can be really confusing sometimes.
We often do not realize the real need for a particular method, or we don't know how to apply it in the real world.
In this post, I'll explain a real use of one of them, the infamous __call__.

Abstract Class

The Python language has abstract class support
Callabe, which helps us to create a class compatible with the Callable protocol, creating a class that inherits from Callable helps us in the correct implementation of the same.

To use this abstract class, you only need to import it from the abc library: from collections.abc import Callabe and inherit it in your own class.

usage

Let's use an example, using a Mapper directly from an ORM (in this case, [SQLAlchemy()]), for a domain object, or class. That is, we will transform the ORM fields into a Python object without any coupling or external dependencies.

Callable Class:

from .dog_domain import Dog
from collections.abc import Callable


class DogMapper(Callable):
    @staticmethod
    def to_domain(dog):
        return Dog(name=dog.name, legs=dog.legs, color=dog.color,) if dog else None

    def __call__(self, dog):
        return self.to_domain(dog)
Enter fullscreen mode Exit fullscreen mode

ORM Class:

from app import db
from .dog_mapper import DogMapper


class Dog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))
    legs = db.Column(db.Integer)
    color = db.Column(db.Integer)

    @property
    def mapper(self):
        return DogMapper()(self)
Enter fullscreen mode Exit fullscreen mode

Domain Class:

class Dog:
    def __init__(self, name, legs, color):
        self.name = name
        self.legs = legs
        self.color = color

    @clasmethod
    def create(cls, name, color, legs=4):
        return cls(name, color, legs,)

Enter fullscreen mode Exit fullscreen mode

Explanation

In this case, we use the mapper property to initialize the mapper, and the conversion to the domain object automatically. This facilitates enough if we had to get some class by id, then import the Mapper and then perform the conversion in the end.

Done this way, callable is only used on demand, and when necessary. Thus, we do not carry out the conversion without a real need.

That way, we can use the mapper directly from the model, right after, such as:

dog = Dog.query.get(id=15).mapper
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this post I tried to demonstrate a real use of a Callable class, I hope that has helped!
If you have any questions or suggestions, don't hesitate to comment. 😉

See ya!

References

Top comments (0)