Mixins en Python



@eduardo_gpg

Número de visitas 157

Tiempo de lectura 2 min

23 Febrero 2024

En esta ocasión hablaremos sobre un patrón muy común en Python que puede ser pasado por alto cuando comenzamos a dar nuestros primeros pasos con el lenguaje y comenzamos con programación orientada a objetos. Me refiero al patrón Mixin. 🐍

En términos simples un Mixin, en Python, es un patrón de diseño que permite añadir funcionalidades extras a una clase; pudiendo así crear clases modulares y reutilizables. Utilizando Mixins hacemos uso del principio: Dont Repeat Your Self y nuestro código será mucho más fácil de leer, testear y mantener.

En primera instancia el tema de Mixins puede sonar complejo, pero realmente no lo es. Basta con utilizar la herencia múltiple que nos ofrece Python y listo.

Veamos un par de ejemplos.

Imaginemos que tenemos 2 clases. User y File. Clases que, si bien no son del mismo tipo, comparten un método en común, el método to_json.

import json 

class UserBase():
    ...

class FileBase():
    ...

class User(UserBase):

    def __init__(self, email, password):
        self.email = email
        self.password = password


    def to_json(self):
        return json.dumps(self.__dict__)

class File(FileBase):

    def __init__(self, path, extension):
        self.path = path
        self.extension = extension


    def to_json(self):
        return json.dumps(self.__dict__)

Para este ejemplo tenemos código duplicado. El método to_json se encuentra en 2 diferentes. Lo cual no es algo bueno. 😵‍💫

Y como sabes, y si no ahora ya lo sabes, el tener código duplicado es un síntoma que nuestro código puede mejorar. En la gran mayoría de los casos abstraer nuestro algoritmo solventara este problema. Y bueno, eso es justamente lo que haremos para este ejemplo.

Creamos una nueva clase Mixin donde definimos el/los métodos que otras clases podrán implementar.

class JSONSerializableMixin:
    def to_json(self):
        return json.dumps(self.__dict__)

Si bien no es necesario usar el sufijo Mixin, te recomiendo lo hagas para seguir un standard de codificación y así tu código sea mucho más legible. 🤯

Con nuestra clase Mixin ya podemos extender funcionalidades. Simplemente heredamos.

class User(UserBase, JSONSerializableMixin):
    def __init__(self, email, password):
        self.email = email
        self.password = passwor



class File(FileBase, JSONSerializableMixin):

    def __init__(self, path, extension):
        self.path = path
        self.extension = extension

Y listo, abstraemos el funcionamiento y lo encapsulamos en una nueva clase.

Utilizando la herencia múltiple que nos ofrece Python podemos extender dicho funcionamiento a una N cantidad de sub clases. Mantenemos el principio Open close y el de responsabilidad única.

Un segundo ejemplo puede ser el siguiente. Donde una N cantidad de clases requiere poder enviar correos electrónicos. Para evitar definir el método send_email N veces, abstraemos, encapsulamos y heredamos.

class EmailNotificationMixin:
    def send_email(self, recipient, subject, message):
        ...

class User(EmailNotificationMixin):
    ...

class Order(EmailNotificationMixin):
    ...

class ShoppingCart(EmailNotificationMixin):
    ...

Consideraciones. 💔

Cómo ya lo mencionamos en una entrega anterior, usar herencia múltiple en Django no siempre es una muy buena idea, esto por el ya conocido Diamon Problem. Para evitar este problema en particular te recomiendo usar el patrón Mixin siempre que sea estrictamente necesario; he intentar que tus clases no hereden de muchas otras más.

Esto último puede sonar muy ambiguo ¿cuanto es: muchas otras más? bueno, eso no te lo puedo responder, será tu experiencia y tu felling quien determine eso.

Aquí un ejemplo de lo que ya considero muchas otras más:

class MyCustomSerializer(TimestampMixin, 
    CustomFieldsMixin, 
    ModelSerializer, 
    LoginRequiredMixin, 
    staff_member_required, 
    ListView):

Y listo, con esto terminaríamos la entrega en esta ocasión. ☕


¿El contenido te resulto de ayuda?

Para poder dejar tu opinión es necesario ser un usuario autenticado. Login

Más Tips y Ejercicios 🐍

Adquiere una subscripción PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 🔓
Nuevo límite: Incrementa tu límite de ejercicios por semana. 🚀
Contenido único: Recibe semanalmente recursos exclusivos de Python (Videos, Artículos y Capitulos del libro PyWombat, comienza como desarrollador Python. 🐍