Mistura Python

Resumo : neste tutorial, você aprenderá sobre as classes mixin do Python e como usá-las para tornar o código reutilizável.

O que é um mixin em Python

Um mixin é uma classe que fornece implementações de métodos para reutilização por várias classes filhas relacionadas. No entanto, a herança não implica um relacionamento é-um.

Um mixin não define um novo tipo. Portanto, não se destina à instanciação de direção.

Um mixin agrupa um conjunto de métodos para reutilização. Cada mixin deve ter um único comportamento específico, implementando métodos intimamente relacionados.

Normalmente, uma classe filha usa herança múltipla para combinar as classes mixin com uma classe pai.

Como o Python não define uma maneira formal de definir classes mixin, é uma boa prática nomear classes mixin com o sufixo Mixin.

Uma classe mixin é como uma interface em Java e C# com implementação. E é como uma característica do PHP .

Exemplo de mixagem em Python

Primeiro, defina uma Personclasse:

class Person:
    def __init__(self, name):
        self.name = nameLinguagem de código:  Python  ( python )

Segundo, defina uma Employeeclasse que herda da Personclasse:

class Employee(Person):
    def __init__(self, name, skills, dependents):
        super().__init__(name)
        self.skills = skills
        self.dependents = dependentsLinguagem de código:  Python  ( python )

Terceiro, crie uma nova instância da Employeeclasse:

if __name__ == '__main__':
    e = Employee(
        name='John',
        skills=['Python Programming''Project Management'],
        dependents={'wife': 'Jane', 'children': ['Alice', 'Bob']}
    )Linguagem de código:  Python  ( python )

Suponha que você queira converter o Employeeobjeto em um dicionário . Para fazer isso, você pode adicionar um novo método à Employeeclasse, que converte o objeto em um dicionário.

Entretanto, você pode querer converter objetos de outras classes em dicionários . Para tornar o código reutilizável, você pode definir uma classe mixin chamada DictMixincomo a seguir:

class DictMixin:
    def to_dict(self):
        return self._traverse_dict(self.__dict__)

    def _traverse_dict(self, attributes: dict) -> dict:
        result = {}
        for key, value in attributes.items():
            result[key] = self._traverse(key, value)

        return result

    def _traverse(self, key, value):
        if isinstance(value, DictMixin):
            return value.to_dict()
        elif isinstance(value, dict):
            return self._traverse_dict(value)
        elif isinstance(value, list):
            return [self._traverse(key, v) for v in value]
        elif hasattr(value, '__dict__'):
            return self._traverse_dict(value.__dict__)
        else:
            return valueLinguagem de código:  Python  ( python )

A DictMixinclasse possui o to_dict()método que converte um objeto em um dicionário.

O _traverse_dict()método itera os atributos do objeto e atribui a chave e o valor ao resultado.

O atributo de um objeto pode ser uma lista, um dicionário ou um objeto com o __dict__atributo. Portanto, o _traverse_dict()método usa o _traverse()método para converter o atributo em valor.

Para converter instâncias da Employeeclasse em dicionários, é Employeenecessário herdar das classes DictMixine :Person

class Employee(DictMixin, Person):
    def __init__(self, name, skills, dependents):
        super().__init__(name)
        self.skills = skills
        self.dependents = dependentsLinguagem de código:  Python  ( python )

Observe que você precisa especificar as classes mixin antes de outras classes.

O seguinte procedimento cria uma nova instância da Employeeclasse e a converte em um dicionário:

e = Employee(
    name='John',
    skills=['Python Programming', 'Project Management'],
    dependents={'wife': 'Jane', 'children': ['Alice', 'Bob']}
)

pprint(e.to_dict())Linguagem de código:  Python  ( python )

Saída:

{'dependents': {'children': ['Alice', 'Bob'], 'wife': 'Jane'},
'name': 'John',
'skills': ['Python Programming', 'Project Management']}Linguagem de código:  Python  ( python )

O seguinte mostra o código completo:

from pprint import pprint


class DictMixin:
    def to_dict(self):
        return self._traverse_dict(self.__dict__)

    def _traverse_dict(self, attributes):
        result = {}
        for key, value in attributes.items():
            result[key] = self._traverse(key, value)

        return result

    def _traverse(self, key, value):
        if isinstance(value, DictMixin):
            return value.to_dict()
        elif isinstance(value, dict):
            return self._traverse_dict(value)
        elif isinstance(value, list):
            return [self._traverse(key, v) for v in value]
        elif hasattr(value, '__dict__'):
            return self._traverse_dict(value.__dict__)
        else:
            return value


class Person:
    def __init__(self, name):
        self.name = name


class Employee(DictMixin, Person):
    def __init__(self, name, skills, dependents):
        super().__init__(name)
        self.skills = skills
        self.dependents = dependents


if __name__ == '__main__':
    e = Employee(
        name='John',
        skills=['Python Programming', 'Project Management'],
        dependents={'wife': 'Jane', 'children': ['Alice', 'Bob']}
    )

    pprint(e.to_dict())Linguagem de código:  Python  ( python )

Componha várias classes mixin

Suponha que você queira converter o Employeeobjeto do para JSON. Para fazer isso, você pode primeiro definir uma nova classe mixin que use o jsonmódulo padrão:

import json

class JSONMixin:
    def to_json(self):
        return json.dumps(self.to_dict())Linguagem de código:  Python  ( python )

E então mude a Employeeclasse para que ela herde a JSONMixinclasse:

class Employee(DictMixin, JSONMixin, Person):
    def __init__(self, name, skills, dependents):
        super().__init__(name)
        self.skills = skills
        self.dependents = dependentsLinguagem de código:  Python  ( python )

O seguinte cria uma nova instância da Employeeclasse e a converte em um dicionário e json:

if __name__ == '__main__':
    e = Employee(
        name='John',
        skills=['Python Programming''Project Management'],
        dependents={'wife': 'Jane', 'children': ['Alice', 'Bob']}
    )

    pprint(e.to_dict())
    print(e.to_json())Linguagem de código:  Python  ( python )

Saída:

{'dependents': {'children': ['Alice', 'Bob'], 'wife': 'Jane'},
'name': 'John',
'skills': ['Python ProgrammingProject Management']}

{"name": "John", "skills": ["Python ProgrammingProject Management"], "dependents": {"wife": "Jane", "children": ["Alice", "Bob"]}}Linguagem de código:  Python  ( python )

O seguinte mostra o código completo:

import json
from pprint import pprint


class DictMixin:
    def to_dict(self):
        return self._traverse_dict(self.__dict__)

    def _traverse_dict(self, attributes):
        result = {}
        for key, value in attributes.items():
            result[key] = self._traverse(key, value)

        return result

    def _traverse(self, key, value):
        if isinstance(value, DictMixin):
            return value.to_dict()
        elif isinstance(value, dict):
            return self._traverse_dict(value)
        elif isinstance(value, list):
            return [self._traverse(key, v) for v in value]
        elif hasattr(value, '__dict__'):
            return self._traverse_dict(value.__dict__)
        else:
            return value


class JSONMixin:
    def to_json(self):
        return json.dumps(self.to_dict())


class Person:
    def __init__(self, name):
        self.name = name


class Employee(DictMixin, JSONMixin, Person):
    def __init__(self, name, skills, dependents):
        super().__init__(name)
        self.skills = skills
        self.dependents = dependents


if __name__ == '__main__':
    e = Employee(
        name='John',
        skills=['Python Programming''Project Management'],
        dependents={'wife': 'Jane', 'children': ['Alice', 'Bob']}
    )

    pprint(e.to_dict())
    print(e.to_json())Linguagem de código:  Python  ( python )

Resumo

  • Uma classe mixin fornece implementações de métodos para reutilização por múltiplas subclasses relacionadas.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *