terça-feira, 5 de março de 2013

Tradução do Artigo "Improving Your Python Produtivity"


Este texto é uma tradução livre do original, escrito em inglês, Improving Your Python Produtivity, escrito por Oz Katz em 02/12/2012.

Melhorando sua Produtividade em Python


Faz alguns anos que programo em python e ainda fico impressionado quão limpo e DRY um código bem escrito em Python pode ser. Há muitas pequenas dicas e truques que eu aprendi ao longo do tempo, principalmente através da leitura do código de projetos open source populares, como Django, Flask, Requests, entre outros.
Aqui estão algumas coisas que eu pincei que às vezes são esquecidos, mas pode realmente ajudar com o trabalho de todos os dias.

1. Dicionários e Conjuntos de compreensão


A maioria dos desenvolvedores Python conhece e usa listas de compreensão. Para aqueles de vocês que não são familiarizados com este conceito, uma lista de compreensão é um caminho curto e mais conciso para criação de listas.

>>> some_list = [1, 2, 3, 4, 5]
>>> another_list = [ x + 1 for x in some_list ]
>>> another_list
[2, 3, 4, 5, 6]

Desde o python 3.1 (também back-portado para Python 2.7), nós podemos utilizar o mesmo idioma para criar conjuntos e dicionários:

>>> # Set Comprehensions
>>> some_list = [1, 2, 3, 4, 5, 2, 5, 1, 4, 8]
>>> even_set = { x for x in some_list if x % 2 == 0 }
>>> even_set
set([8, 2, 4])

>>> # Dict Comprehensions
>>> d = { x: x % 2 == 0 for x in range(1, 11) }
>>> d
{1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False, 10: True}

No primeiro exemplo, criamos um conjunto de itens únicos a partir de some_list, considerando apenas os números pares. O exemplo seguinte mostra a criação de um dicionário em que as chaves são números inteiros de 1 a 10 (inclusive) e os valores são valores booleanos, indicando se a chave é ou não um número par.

Outra característica que vale a pena mencionar aqui é a disponibilidade definir conjuntos. Podemos criar um conjunto simplesmente fazendo:

>>> my_set = {1, 2, 1, 2, 3, 4}
>>> my_set
set([1, 2, 3, 4])

Ao invés de usar o método embutido set().

2. Usando um objeto Counter para, bem, contar.


Este é uma dica muito óbvia mas muitas vezes é esquecida. Contar coisas é uma tarefa muito comum para a maioria dos desenvolvedores. Não é uma coisa muito difícil de fazer (na maioria dos casos), mas existem maneiras de tornar este trabalho ainda mais fácil.

A biblioteca Python collections inclui uma subclasse da built-in dict, criado especificamente para esta tarefa:

>>> from collections import Counter
>>> c = Counter('hello world')
>>> c
Counter({'l': 3, 'o': 2, ' ': 1, 'e': 1, 'd': 1, 'h': 1, 'r': 1, 'w': 1})
>>> c.most_common(2)
[('l', 3), ('o', 2)]

3. Imprimindo JSON de forma legível


JSON é um ótimo formato de serialização, largamente usado hoje por APIs e web-services. Embora seja um pouco legível quando se trabalha com o módulo json nativo, torna-se muito difícil de entender estruturas de dados maiores a olho nu, pois se apresentam como uma linha longa e contínua.

Para tornar as coisas um pouco mais fáceis, podemos usar o argumento 'indent' para "imprimir bonitinho" nossos objetos JSON. Isso é especialmente útil quando se trabalha de forma interativa a partir do REPL ou para log:

>>> import json
>>> print(json.dumps(data))  # No indention
{"status": "OK", "count": 2, "results": [{"age": 27, "name": "Oz", "lactose_intolerant": true}, {"age": 29, "name": "Joe", "lactose_intolerant": false}]}
>>> print(json.dumps(data, indent=2))  # With indention
{
  "status": "OK",
  "count": 2,
  "results": [
    {
      "age": 27,
      "name": "Oz",
      "lactose_intolerant": true
    },
    {
      "age": 29,
      "name": "Joe",
      "lactose_intolerant": false
    }
  ]
}

Além disso, certifique-se de fazer checkout do módulo pprint que serve para imprimir praticamente qualquer coisa.

4. Criando um web-service de forma rápida e suja


Às vezes, precisamos de uma maneira muito simples e rápida de fazer algum tipo de RPC entre serviços ou máquinas. Tudo o que queremos é uma maneira simples do programa A chamar um método do programa B, possivelmente, em outra máquina - para uso interno.

Eu não defendo essa técnica de criar qualquer coisa que não seja unicamente para consumo internos. Mas nós podemos usar um protocolo chamado XML-RPC (com suas bibliotecas Python correspondentes) para este tipo de trabalho.

Aqui vai um exemplo de um serviço rápido e sujo para leitura de arquivos, utilizando o módulo SimpleXMLRPCServer:

from SimpleXMLRPCServer import SimpleXMLRPCServer

def file_reader(file_name):
    with open(file_name, 'r') as f:
        return f.read()

server = SimpleXMLRPCServer(('localhost', 8000))
server.register_introspection_functions()

server.register_function(file_reader)

server.serve_forever()

Com o respectivo cliente:

import xmlrpclib
proxy = xmlrpclib.ServerProxy('http://localhost:8000/')
proxy.file_reader('/tmp/secret.txt')

Agora temos uma espécie de leitor de arquivo remoto, sem dependências externas e apenas um pequeno código (E, claro, não há segurança de qualquer tipo, de modo que tente isso só em casa).

5. A incrível comunidade de código aberto Python


Bem, eu só cobri coisas disponíveis na biblioteca padrão do Python, que, se você tem o Python instalado, já está incluído na sua distribuição. Para a maioria das outras tarefas há uma tonelada de bibliotecas de terceiros mantidas pela comunidade à sua disposição.

Aqui está minha checklist para escolher uma ótima biblioteca open source confiável:

Uma ótima biblioteca open source deve ...

  • Conter uma licença clara e que se adeque ao seu caso particular.
  • Ser ativamente mantida e desenvolvida (ou que aceite com boa vontade suas intervenções).
  • Ser instalável através do comando 'pip' para facilitar o seu uso. 
  • Ter uma suíte de testes com uma cobertura decente.

Se você encontrar uma boa biblioteca que se adapte às suas necessidades não seja tímido - a maioria dos projetos de código aberto aceita contribuições e assistências, mesmo se você não for um veterano Python. Ajudas são quase sempre bem-vindos.

Como sempre, eu ficaria feliz em aprender com a sua experiência e, claro, discutir as dicas que eu apresentei! Poste seus comentários aqui abaixo, ou pelo Twitter ozkatz100.


Referências


  1. http://ozkatz.github.com/improving-your-python-productivity.html
  2. https://twitter.com/ozkatz100
  3. http://en.wikipedia.org/wiki/Don't_repeat_yourself
  4. https://www.djangoproject.com/
  5. http://flask.pocoo.org/
  6. http://docs.python-requests.org/en/latest/
  7. http://www.python.org/download/releases/2.7/
  8. http://docs.python.org/2/library/collections.html
  9. http://docs.python.org/2/library/pprint.html
  10. http://en.wikipedia.org/wiki/XML-RPC
  11. http://docs.python.org/2/library/simplexmlrpcserver.html