12 de mar de 2012

bpython, um belo console de Python

Um dos pontos fortes da linguagem Python, é a possibilidade de prototipar rapidamente atráves do seu poderoso console.

Para quem sentia necessidade de maior agilidade usando o console, o IPython, trouxe várias features, como o uso de instrospecção, que permite o auto-complete de métodos e atributos e acesso as Docstrings, dentre outras características que ajudam os desenvolvedores.

Eu descobri essa semana outro interpretador, o bpython. Com features parecidas as do IPython, mas um layout mais próximo do console original, ele já poderia substituir o IPython sem problemas. Mas algumas features são bem chamativas, dentre elas destacaria, o suporte ao compartilhamento de código via bpaste e a possibilidade de salvar o código em arquivo.

fonte: http://bpython-interpreter.org




Para mais informações, acesse a documentação do bpython.

11 de mar de 2012

List Comprehensions em Python

List comprehensions, em ciência da computação, é um construtor de listas que se baseia em outras listas pré-existentes.

Esse conceito não é novo e data dos anos 60's. Mas o termo comprehension foi usado pela primeira vez na linguagem NPL.

E as List Comprehension tem como origem as representação do conjuntos da matemática:

{x ∈ N | 0 < x < 7}
Lê-se: x pertence ao conjunto dos Naturais, tal que 0 é menor que x e x menor que 7. O que restringiria esse conjunto a {1, 2, 3, 4, 5, 6}.

Em Python, uma List comprehension tem a seguinte sintaxe:

[x * 2 for x in lista]
Nesse exemplo abaixo, multiplicamos os itens da lista por 2, atribuimos à variável nova_lista:

>>> lista = [1, 2, 3, 4, 5]  
>>> nova_lista = [x * 2 for x in lista]  
>>> nova_lista  
[2, 4, 6, 8, 10]  
Sendo que o 'x * 2' é executado em cada item da lista. Um código mais limpo  e intuitivo do que uma versão usando a builtin function map.

>>> def vezes_2(n):
...     return n * 2
...     
... 
>>> map(vezes_2, range(6))
[0, 2, 4, 6, 8, 10]
Poderiamos fazer essa operação com uma lambda function.

>>> map(lambda x: x * 2, range(6))
[0, 2, 4, 6, 8, 10]

Um código análogo sem List comprehension:

>>> lista = [1, 2, 3, 4, 5]  
>>> nova_lista = []  
>>> for x in lista:  
...   nova_lista.append(x * 2)  
...    
...  
>>>  
>>> nova_lista  
[2, 4, 6, 8, 10]  
Dentro das  List comprehensions ainda se pode usar condicionais, para filtrar elementos na criação das novas listas.

>>> frase = ['o', 'rato', 'roeu', 'a', 'roupa', 'do', 'rei', 'de', 'roma']
>>> [p for p in frase if p[0] == 'r'] 
['rato', 'roeu', 'roupa', 'rei', 'roma']
Aqui eu verifico se a primeira letra da palavra é 'r'.

Criei um pequeno script para comparar a performance das List comprehensions. Escrevi duas funções, uma usando List comprehensions e outra não, que criam uma lista com os números pares entre 0 e 1000000. Para fazer a comparação usei a biblioteca cProfile.

def foo():  
    l = []  
    for i in range(1000000):  
        if i % 2 == 0:  
            l.append(i)

def foo_listcomp():  
    l = [i for i in range(1000000) if i % 2 == 0]  

cProfile.run('foo()')  
cProfile.run('foo_listcomp()')  
Executando o código.

$ python bench.py  
   500004 function calls in 1.739 seconds  


Ordered by: standard name  

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.009    0.009    1.739    1.739 <string>:1(<module>)
     1    0.936    0.936    1.730    1.730 bench.py:61(foo)
500000    0.769    0.000    0.769    0.000 {method 'append' of 'list'...
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof...
     1    0.025    0.025    0.025    0.025 {range}
  

   4 function calls in 0.165 seconds  

Ordered by: standard name  

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.015    0.015    0.165    0.165 :1()
     1    0.125    0.125    0.150    0.150 bench.py:67(foo_listcomp)
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof...
     1    0.024    0.024    0.024    0.024 {range}  
O código convencional chega a ser 10 vezes mais lento que o código que utiliza List comprehension. 1.739 segundos contra 0.165.

A performance e a simplicidade do código justifica o uso das List comprehensions quando se quer criar listas a partir de listas, sua finalidade semântica. Mas quando a lógica envolvida na geração da nova lista é muito complexa, o seu uso pode diminuir a legibilidade do código drasticamente.

Referências:
Google Style Guide
Documentação Python
The History of Python

3 de mar de 2012

Palestrando sobre Coding Dojo

Sempre fui adepto do aprendizado, em qualquer área do conhecimento. E assim que conheci o Coding Dojo, percebi como ele seria um aliado forte no aprendizado de programação.

Depois de organizar alguns Dojos com alguns amigos da Fatec São José dos Campos, recebemos o convite da amiga/professora Amita Muralikrishna para organizarmos os Dojo na Etec de São José dos Campos.

Além de gostar de aprender, gosto de compartilhar meu conhecimento, e achei que divulgar os encontros seria uma ótima forma de propagar os benefícios do Dojo. Daí surgiu a ideia de fazer uma palestra/convite aos alunos dos cursos tecnicos da Etec relacionados a tecnologia.

A palestra foi agendada em cima da hora, pegando os alunos de surpresa, mas o resultado parece ter sido muito bom. Apesar da timidez da maioria, eles se mostraram interessados e cheios de energia em aprender. Eu tentei fazé-los não se sentirem intimidados a participarem dos Dojos, mesmo os que estavam começando o curso.

Falar para adolescentes é algo que pode intimidar alguns, mas para romper as barreiras da idade, tentei fazer uma palestra divertida para poder atrair a atenção dos participantes e despertar o interesse em participar das sessões de Coding Dojos que aconteceriam em seu colégio.

A experiência foi, com certeza, um grande aprendizado para mim. O feedbacks dos professores foram muito motivadores. Espero que a palestra se converta em participação em massa dos alunos e isso, consequentemente, se transforme em um melhor desempenho dos alunos nas aulas.