15.12.2022 Views

Python Eficaz

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Todavia, tudo isso parece redundante. Já havíamos declarado o nome do campo

quando, no corpo do comando class, atribuímos o campo Customer.first_name

ao objeto Field. Por que precisaria passar novamente o campo nome ('first_name'

neste caso) ao construtor Field?

O problema é que a ordem das operações na definição da classe Customer é

invertida em relação a como é lida, da esquerda para a direita. Primeiro, o

construtor Field é chamado como Field('first_name'). Depois, o valor de retorno

é atribuído a Customer.field_name. Não há maneira de fazer com que Field saiba

de antemão qual atributo de classe será atribuído a ele.

Para eliminar essa redundância, podemos usar uma metaclasse. As metaclasses

permitem acessar o comando class diretamente e agir assim que o corpo de class

terminar de ser processado. Neste caso, podemos usar a metaclasse para atribuir

Field.name a Field.internal_name no descritor automaticamente, em vez de

especificar o campo manualmente uma infinidade de vezes.

class Meta(type):

def __new__(meta, name, bases, class_dict):

for key, value in class_dict.items():

if isinstance(value, Field):

value.name = key

value.internal_name = '_' + key

cls = type.__new__(meta, name, bases, class_dict)

return cls

No exemplo de código a seguir, definimos uma classe-base que usa a metaclasse.

Todas as classes que representam linhas em bancos de dados precisam herdar

esta classe para garantir que a metaclasse seja usada por todas:

class DatabaseRow(object, metaclass=Meta):

pass

Para trabalhar com a metaclasse, o descritor de campo fica inalterado grande

parte do tempo. A única diferença é que ele não mais requer que quaisquer

argumentos sejam passados para seu construtor. Em vez disso, seus atributos têm

valores preenchidos pelo método Meta.__new__ do código anterior.

class Field(object):

def __init__(self):

www.full-ebook.com

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!