/metapython

Primary LanguagePythonOtherNOASSERTION

MetaPython: quando trocamos os encanamentos!

Python é versátil 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 expressão de uma linha. Usando os vários recursos entre metaclasses, decorators, introspecção dos frames de execução, são mostrados exemplos de cada uma dessas coisas for fun & profit.

  • Function Decorators

Permitem processar um objeto função assim que ele é instanciado.

O processo permite mudar atributos de uma função,

permite fazer o ^wrap de uma função com código que muodifica seu comportamento.

As vezes até entendemos o conceito, mas não sabemos onde usar

Um exemplo simples, pode ser anotação de tipos.

def sum(a, b): if not is instance(a, int) or not isinstance(b, int): raise TypeError

<<static.py

  • polimorfismo

Em linguagens estáticas se escreve várias vezes um método

para cada combinação possível de parâmetros.

Só com decorators de métodos -

em vez de devolver uma função:

  • manter um dicionário com o nome dos métodos estáticos já registrados para cada classe

  • devolver um objeto especial que: -- com informação dos métodos homônimos e tipos de atributos -- um método call que faça o dispatch adequado

Não pode ser feito exclusivamente com metaclasse

métodos com mesmo nome se sobrescreverem durante o parsing

só o último método definido seria passado aos wrappers de metaclasse

meta-classes para sinalizar uma nova classe,

evitando que métodos de classes diferentes se confundam

<<polymorph.py

  • Tail Recursion

No dia que fiz, achei um post do BDFL dizendo "não faça"

Escrito dois dias antes

Há várias implementações mais robustas também

Mas... #comofas?

Com um @decorator -- anotamos que a função foi chamada

e realizamos a chamada original dentro de um try: except

Se, antes do retorno, houver outra chamada à mesma função anotamos os parâmetros levantamos uma exceção!

   e estamos de volta no contexto do decorator
   que pode realizar uma nova chamada
   
   com os parâmetros salvos, mas sem
   aumentar a profundidade da pilha

<<tailrecusion.py

  • lazy execution

Um objeto python só "faz" alguma coisa quando é invocado um dos métodos "under under"

Basta um decorator que retorne um objeto que se "lembre" da função e dos parâmetros usados

e disponibilize todos os métodos "under under" do data_model

E só quando um dos métodos "under under" for chamado é que a função original é executada.

<<lazy_decorator.py

  • Atributos Privados

Em tese só podem ser acessados pela instância "dona" do atributo

implementamos nos hooks de acesso a atributos da classe uma verificação de identidade

Para isso instropecta-se o frame apropriado na pilha de execução

import sys sys._getframe(level)

E verifica-se se quem chamou o método para recuperar um atributo tem esse direito

<<privateattr.py

  • Mudando a 'cara' da linguagem:

Não faça, exceto por diversão!

Para parcer Scheme, o principal é "define" coisas num grupo de parenteses externos

E funções de uma letra que usem os argumentos como o scheme usa as listas

<<pyschemificator.py

  • Programação Orientada a Aspectos

Uma forma de adicionar todo um tipo de comportamento a determinado grupo de métodos em sistemas já em funcionamento.

Com isso o código pode acumular muito código repetitivo

em logging, checagem de parâmetros, gerenciamento de cache, verificação de integridade

A idéia de "aspect orientation" é permitir que comportamento comum fique num canto comum do código,

e, baseando-se apenas em tipos de parâmetros, ou padrões no nome dos métodos, esse código 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 várias implementações usando a introspecção de python para cobrir aspect oriented programing para todos os gostos

Com metaclasses, podemos fazer em 100 linhas de código.

<<aspect.py