OTHER License
MetaPython: quando trocamos os encanamentos!
Python verstil o suficiente para, sem quebrar as regras da linguagem, podermos implementar polimorfismo, tail recursion, lazy execution, checagem de tipos, atributos privados, mudar o "jeito" da linguagem para que lembre LISP, ou Forth, ou ainda fazer tudo em uma nica expresso de uma linha. Usando os vrios recursos entre metaclasses, decorators, introspeco dos frames de execuo, so mostrados exemplos de cada uma dessas coisas for fun & profit.
Permitem processar um objeto funo assim que ele instanciado.
O processo permite mudar atributos de uma funo,
permite fazer o ^wrap de uma funo com cdigo que muodifica seu comportamento.
As vezes at entendemos o conceito, mas no sabemos onde usar
Um exemplo simples, pode ser anotao de tipos.
def sum(a, b): if not is instance(a, int) or not isinstance(b, int): raise TypeError
<<static.py
Em linguagens estticas se escreve vrias vezes um mtodo
para cada combinao possvel de parmetros.
S com decorators de mtodos -
em vez de devolver uma funo:
manter um dicionrio com o nome dos mtodos estticos j registrados para cada classe
devolver um objeto especial que: -- com informao dos mtodos homnimos e tipos de atributos -- um mtodo call que faa o dispatch adequado
No pode ser feito exclusivamente com metaclasse
mtodos com mesmo nome se sobrescreverem durante o parsing
s o ltimo mtodo definido seria passado aos wrappers de metaclasse
meta-classes para sinalizar uma nova classe,
evitando que mtodos de classes diferentes se confundam
<<polymorph.py
No dia que fiz, achei um post do BDFL dizendo "no faa"
Escrito dois dias antes
H vrias implementaes mais robustas tambm
Mas... #comofas?
Com um @decorator -- anotamos que a funo foi chamada
e realizamos a chamada original dentro de um try: except
Se, antes do retorno, houver outra chamada mesma funo anotamos os parmetros levantamos uma exceo!
e estamos de volta no contexto do decorator
que pode realizar uma nova chamada
com os parmetros salvos, mas sem
aumentar a profundidade da pilha
<<tailrecusion.py
Um objeto python s "faz" alguma coisa quando invocado um dos mtodos "under under"
Basta um decorator que retorne um objeto que se "lembre" da funo e dos parmetros usados
e disponibilize todos os mtodos "under under" do data_model
E s quando um dos mtodos "under under" for chamado que a funo original executada.
<<lazy_decorator.py
Em tese s podem ser acessados pela instncia "dona" do atributo
implementamos nos hooks de acesso a atributos da classe uma verificao de identidade
Para isso instropecta-se o frame apropriado na pilha de execuo
import sys sys._getframe(level)
E verifica-se se quem chamou o mtodo para recuperar um atributo tem esse direito
<<privateattr.py
No faa, exceto por diverso!
Para parcer Scheme, o principal "define" coisas num grupo de parenteses externos
E funes de uma letra que usem os argumentos como o scheme usa as listas
<<pyschemificator.py
Uma forma de adicionar todo um tipo de comportamento a determinado grupo de mtodos em sistemas j em funcionamento.
Com isso o cdigo pode acumular muito cdigo repetitivo
em logging, checagem de parmetros, gerenciamento de cache, verificao de integridade
A idia de "aspect orientation" permitir que comportamento comum fique num canto comum do cdigo,
e, baseando-se apenas em tipos de parmetros, ou padres no nome dos mtodos, esse cdigo comum seja executado apropriadamente.
Em Java, tiveram que criar um ^fork da linguagem, chamado "aspectj" que inclui o tipo "aspect" ao lado de "classes" e "interfaces".
Em python, poderiamos usar s method decorators.
Existem vrias implementaes usando a introspeco de python para cobrir aspect oriented programing para todos os gostos
Com metaclasses, podemos fazer em 100 linhas de cdigo.
<<aspect.py