Callable Python
Tags: python, programming, webdev, beginners
Published: 2023-01-10 13:45:24

## 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](https://docs.python.org/pt-br/3/library/collections.abc.html#collections.abc.Callable), 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:

``` python
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)
```

ORM Class:

``` python
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)
```

Domain Class:

``` python
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,)

```


## 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:

``` python
dog = Dog.query.get(id=15).mapper
```

## 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. :wink:

See ya!

## References

- [Fluent Python](https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/) 
- [Clean Architecture](https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/?_gl=1*oabtnq*_ga*NDY5NTUwNzQ3LjE2NzMzNTgwOTg.*_ga_092EL089CH*MTY3MzM1ODEwMC4xLjEuMTY3MzM1ODExNC40Ni4wLjA.) 
- [Domain Driven Design](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software-ebook/dp/B00794TAUG/ref=sr_1_1?crid=38ZVRV16CDUMU&dchild=1&keywords=domain+driven+design&qid=1588281345&s=books&sprefix=domain+driven%2Cstripbooks-intl-ship%2C358&sr=1-1)