DEV Community

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

Posted on

Callable Python

Introdução

Python tem diversos métodos mágicos que, às vezes, podem ser realmente confusos.
Muitas vezes não percebemos a real necessidade de um determinado método, ou não
sabemos como aplicá-lo no mundo real.

Nesse post, explicarei uma utilização real de um deles, o famoso __call__.

Classe Abstrata

A linguagem Python tem suporte à classe abstrata
Callabe,
que nos auxilia na criação de uma classe compatível com o protocolo Callable,
criando uma classe que herde de Callable nos auxilia na correta implementação da
mesma.

Para utilizar esse classe abstrata basta importá-la da biblioteca abc: from
collections.abc import Callabe
e herdá-la na sua própria classe.

Utilização

Nesse post, irei exemplificar com a utilização de um Mapper direto de um ORM (no
caso, SQLAlchemy), para um objeto, ou classe, de domínio.
Ou seja, iremos transformar os campos do ORM, para um objeto Python sem nenhum
acoplamento ou dependências externas.

Classe Callable:

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)

Classe ORM de exemplo:

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)

Classe de domínio:

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

Explicação

Nesse caso, utilizamos a property mapper para realizar a inicialização do
mapper, e a conversão para o objeto de domínio automaticamente. O que facilita
bastante caso tivéssemos que obter alguma classe por id, depois importar o
Mapper e depois realizar a conversão.

Feito dessa forma, o callable é utilizado somente sob demanda, e quando
necessário. Assim não realizamos a conversão sem que haja real necessidade.

Assim, podemos utilizar o mapper diretamente do model, logo na sequência,
como por exemplo:

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

Conclusão

Nesse post tentei demonstrar uma utilização real de uma classe Callable, espero
que tenha ajudado!
Caso tenha alguma dúvida, ou sugestão, não hesite em comentar. 😉

Nos vemos por aí!

Referências

Mais posts como esse, olhe no meu blog

Top comments (0)