Python para quem sabe Python Turma 0, aula 4 Metaclasses, programação funcional e programação assíncrona Exercício: execucao.py ● ● ● ● Para entender como o interpretador Python lê um arquivo .py Tudo é executável Mas às vezes, executar significa “definir, compilar e atribuir um objeto” (ex. funções e classes) O que é preciso executar para definir um desses objetos? https://github.com/oturing/ppqsp/blob/master/metaprog/execucao.py Recapitulando: Descritores Recapitulando: Descritores e metaclasses Descritor com nome automático class Quantidade(object): def __set__(self, instance, valor): # nome atribuido Just-In-Time, idéia do Gustavo Fonseca [1] if not hasattr(self, 'nome_atr'): for nome, atr in instance.__class__.__dict__.items(): if atr is self: self.nome_atr = '__'+nome break else: # only if the for loop terminates without break assert False, 'descriptor not found in class' if valor < 1: raise TypeError('%s deve ser > 0' % self.nome_atr[2:]) setattr(instance, self.nome_atr, valor) def __get__(self, instance, owner): return getattr(instance, self.nome_atr) class C(object): def __init__(self, x): self.x = x x = Quantidade() [1] http://gusfonseca.wordpress.com/2011/12/11/um-pouco-sobre-descritores-em-python/ O caminho até metaclasses ● No github.com/oturing/ppsqp [1] ● pedido3.py: descritor com nome automático ● pedido4.py e pedido5.py: ● ● primeiro exemplo do atributo __metaclass__ classe abstrata ValidatedDescriptor para facilitar a criação de novos descritores com validação – uso do padrão Template Method (GoF 325) [1] https://github.com/oturing/ppqsp/tree/master/atributos/metaclasses Template Method (GoF 325) ● ● Auto-delegação (A. Martelli) Usando Template Method, uma classe abstrata deixa suas subclasses definirem um ou mais passos de um algoritmo O caminho até metaclasses (2) ● pedido6.py: ● ● registro da ordem dos descritores via ValidatedDescriptor.__new__ primeiro exemplo do método __new__ O caminho até metaclasses (3) ● pedido7.py: ● ● ● metaclasse OrderedModelMeta para criar atributo _ordered_descriptors em cada nova classe deste tipo classe OrderedModel para facilitar o uso da metaclasse, permitindo que as subclasses herdem o atributo __metaclass__ = OrderedModelMeta registro da ordem dos descritores movido de ValidatedDescriptor para a nova classe abstrata OrderedDescriptor – separação de responsabilidades: uma classe cuida de validação, a outra de ordenação O caminho até metaclasses (4) ● pedido8.py: ● lógica de atribuição de nomes aos descritores movida para o método __new__ da metaclasse OrderedModelMeta – ● aproveita o fato de que este método __new__ já tem que percorrer todos os atributos do dict da nova classe, e evita o custo de fazer um laço a cada __set__ inicial e um teste hasattr em todas as chamadas de __set__ método list_ordered_descriptors na classe OrderedModel para evitar que as subclasses tenha que acessar o atributo de classe que mantém a lista (_ordered_descriptors) O caminho até metaclasses (5) ● pedido9.py: ● ● definição de um __init__ genérico em OrderedModel que recebe os argumentos posicionais e os atribui em aos atributos ordenados desta forma as subclasses de OrderedModel não precisam implementar seus __init__, evitando a repetição dos nomes dos atributos associados aos OrderedDescriptors Programação funcional ● Paradigma que enfatiza o uso de funções puras, composição de funções, funções de ordem superior e estruturas de dados imutáveis ● ● ● Funções puras = sem efeitos colaterais: não modificam seus argumentos nem alteram o estado do sistema de nenhuma maneira, mas apenas devolvem um valor Composição de funções: aplicação de uma função ao resultado de uma outra Funções de ordem superior: funções que recebem funções como argumentos ou devolvem funções como resultado Funções como objetos de 1ª classe ● objetos de 1ª classe ● ex: números, strings, listas, etc. (até classes em Python) ● podem ser construídos em tempo de execução ● ● em Python, funções são objetos de 1ª classe ● ● podem ser atribuídos a variáveis, passados como argumentos, devolvidos como resultados de funções isso ocorre em muitas linguagens modernas, mas não em Java e nem em Pascal em Python, funções são instâncias de function, e têm seus próprios atributos Funções são objetos de 1ª classe função de ordem superior >>> >>> def def dobro(n): dobro(n): ... """Devolve ... """Devolve duas duas vezes vezes n""" n""" ... return ... return n*2 n*2 >>> >>> dobro(21) dobro(21) 42 42 >>> >>> dobro('X') dobro('X') 'XX' 'XX' >>> >>> dobro dobro <function <function dobro dobro at at 0x990b17c> 0x990b17c> >>> >>> type(dobro) type(dobro) <type <type 'function'> 'function'> >>> >>> x2 x2 == dobro dobro >>> >>> x2(1234) x2(1234) 2468 2468 >>> >>> map(dobro, map(dobro, [11, [11, 22, 22, 33]) 33]) [22, [22, 44, 44, 66] 66] Funções de ordem superior ● ● Funções que recebem funções como argumento ou devolvem funções como resultado Exemplos importantes em Python: ● map, filter – ● reduce – ● fazem o mesmo que list comprehensions substituído por sum, all e any nos casos mais comuns sorted, list.sort – muito úteis Recursos para programação funcional em Python ● Módulo functools ● ● Módulo itertools ● ● várias funções de ordem superior inspirado pelas biblioteca padrão de Haskell, uma das linguagens funcionais mais “puras” Módulo operator ● ● operadores básicos de Python implementados como funções muito úteis: attrgetter e itemgetter Programação asíncrona Programação assíncrona ● ● Também conhecida como programação orientada a eventos Aplicações: sistemas reativos ● ● ● reagem a eventos externos ex: servidores, aplicações GUI, jogos, controladores embutidos em máquinas Na moda por causa do problema C10k ● como lidar com 10.000 conexões? – 10.000 threads não é a resposta certa Bibliotecas para programação de aplicações de rede assíncronas ● ● Módulos select, asyncore e asyncchat do Python padrão Twisted: 10 anos de história, muitos protocolos, tem uma cultura e terminologia própria, peculiar ● baseado em callbacks, com suporte recente a corotinas ● Tornado: recente, mais enxuto que o Twisted ● gevent: baseado em co-rotinas ● outras opções... Temas I ● ● ● sobrecarga de operadores (ou como fazer uma API Pythonica) iteráveis e iteradores (ou como percorrer qualquer coisa com um simples for) geradores e co-rotinas (ou outro jeito de organizar meus algoritmos) Temas II ● ● ● ● acesso, criação e remoção dinânica de atributos (tudo sobre atributos básicos) propriedades e descritores (encapsulamento com atributos, ou como funcionam os modelos do Django) meta-programação, criação dinâmica de classes e funções (ou monkeypatching) metaclasses (ou como explodir sua mente criando classes turbinadas) Temas III ● ● ● ● programação funcional (ou aquele outro paradigma que tá na moda) decoradores de funções (ou meta-programação com arte) programação assíncrona (ou como fazer muitas coisas ao mesmo tempo sem usar threads) gerenciadores de contexto (ou como usar o comando with)