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 type
metaclasse para criar outras classes.
Por exemplo, o seguinte define uma Person
classe:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
Linguagem de código: Python ( python )
Quando Python executa o código, ele usa a type
metaclasse para criar a Person
classe. A razão é que a Person
classe usa a type
metaclasse por padrão.
A definição explícita Person
da classe é assim:
class Person(object, metaclass=type):
def __init__(self, name, age):
self.name = name
self.age = age
Linguagem de código: Python ( python )
O metaclass
argumento 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 Human
que tenha os freedom
atributos definidos True
como 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 Person
classe que usa a Human
metaclasse:
class Person(object, metaclass=Human):
def __init__(self, name, age):
self.name = name
self.age = age
Linguagem de código: Python ( python )
A Person
classe terá o freedom
atributo 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 Human
metaclasse 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 Human
metaclasse para criar uma Person
classe com as variáveis de classe country
e freedom
definidas como USA
e True
respectivamente:
class Person(object, metaclass=Human, country='USA', freedom=True):
def __init__(self, name, age):
self.name = name
self.age = age
Linguagem 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.