Metaclasse Python

Resumo : neste tutorial, você aprenderá sobre a metaclasse Python e entenderá como o Python usa as metaclasses para criar outras classes.

Introdução à metaclasse Python

Uma metaclasse é uma classe que cria outras classes. Por padrão, Python usa a typemetaclasse para criar outras classes.

Por exemplo, o seguinte define uma Personclasse:

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

Quando Python executa o código, ele usa a typemetaclasse para criar a Personclasse. A razão é que a Personclasse usa a typemetaclasse por padrão.

A definição explícita Personda classe é assim:

class Person(object, metaclass=type):
    def __init__(self, name, age):
        self.name = name
        self.age = ageLinguagem de código:  Python  ( python )

O metaclassargumento permite especificar qual classe de metaclasse usar para definir a classe. Portanto, você pode criar uma metaclasse customizada que tenha sua própria lógica para criar outras classes. Ao usar uma metaclasse personalizada, você pode injetar funcionalidade no processo de criação de classe.

Exemplo de metaclasse Python

Primeiro, defina uma metaclasse personalizada chamada Humanque tenha os freedomatributos definidos Truecomo padrão:

class Human(type):
    def __new__(mcs, name, bases, class_dict):
        class_ = super().__new__(mcs, name, bases, class_dict)
        class_.freedom = True
        return class_Linguagem de código:  Python  ( python )

Observe que o __new__método retorna uma nova classe ou um objeto de classe.

Segundo, defina a Personclasse que usa a Humanmetaclasse:

class Person(object, metaclass=Human):
    def __init__(self, name, age):
        self.name = name
        self.age = ageLinguagem de código:  Python  ( python )

A Personclasse terá o freedomatributo conforme mostrado nas variáveis ​​de classe :

pprint(Person.__dict__)Linguagem de código:  Python  ( python )

Saída:

mappingproxy({'__dict__': <attribute '__dict__' of 'Person' objects>,
              '__doc__': None,
              '__init__': <function Person.__init__ at 0x000001E716C71670>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Person' objects>,
              'freedom': True})Linguagem de código:  Python  ( python )

Junte tudo.

from pprint import pprint


class Human(type):
    def __new__(mcs, name, bases, class_dict):
        class_ = super().__new__(mcs, name, bases, class_dict)
        class_.freedom = True
        return class_


class Person(object, metaclass=Human):
    def __init__(self, name, age):
        self.name = name
        self.age = age


pprint(Person.__dict__)Linguagem de código:  Python  ( python )

Parâmetros de metaclasse

Para passar parâmetros para uma metaclasse, você usa a palavra-chave argumentos. Por exemplo, o seguinte redefine a Humanmetaclasse que aceita argumentos de palavras-chave, onde cada argumento se torna uma variável de classe:

class Human(type):
    def __new__(mcs, name, bases, class_dict, **kwargs):
        class_ = super().__new__(mcs, name, bases, class_dict)
        if kwargs:
            for name, value in kwargs.items():
                setattr(class_, name, value)
        return class_Linguagem de código:  Python  ( python )

O seguinte usa a Humanmetaclasse para criar uma Personclasse com as variáveis ​​de classe countrye freedomdefinidas como USAe Truerespectivamente:

class Person(object, metaclass=Human, country='USA', freedom=True):
    def __init__(self, name, age):
        self.name = name
        self.age = ageLinguagem de código:  Python  ( python )

Aqui estão as variáveis ​​da classe Person:

pprint(Person.__dict__)Linguagem de código:  Python  ( python )

Saída:

mappingproxy({'__dict__': <attribute '__dict__' of 'Person' objects>,
              '__doc__': None,
              '__init__': <function Person.__init__ at 0x0000018A334235E0>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Person' objects>,
              'country': 'USA',
              'freedom': True})Linguagem de código:  Python  ( python )

Junte tudo.

from pprint import pprint


class Human(type):
    def __new__(mcs, name, bases, class_dict, **kwargs):
        class_ = super().__new__(mcs, name, bases, class_dict)
        if kwargs:
            for name, value in kwargs.items():
                setattr(class_, name, value)
        return class_


class Person(object, metaclass=Human, freedom=True, country='USA'):
    def __init__(self, name, age):
        self.name = name
        self.age = age


pprint(Person.__dict__)Linguagem de código:  Python  ( python )

Quando usar metaclasses

Aqui está a citação de Tim Peter , que escreveu o Zen of Python:

Metaclasses são magias mais profundas com as quais 99% dos usuários nunca deveriam se preocupar. Se você se pergunta se precisa deles, você não precisa (as pessoas que realmente precisam deles sabem com certeza que precisam deles e não precisam de uma explicação sobre o porquê).

Tim Pedro

Na prática, muitas vezes você não precisa usar metaclasses, a menos que mantenha ou desenvolva o núcleo de grandes estruturas como o Django.

Resumo

  • Uma metaclasse é uma classe que cria outras classes.

Deixe um comentário

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