python

O Paradoxo Python

Posted on 11 \d\e janeiro \d\e 2011. Filed under: computers, python |

Este texto é uma tradução autorizada do texto The Python Paradox de autoria de Paul Graham, feita por tellarin.
Texto original: The Python Paradox, autoria de Paul Graham.
Tradução por Börje Karlsson (tellarin at sounerd dot com).
Eventuais comentários entre colchetes são adições pelo tradutor, não existindo na versão original.

Numa palestra recente, eu [Paul] disse algo que perturbou muitas pessoas: que poderia-se conseguir programadores mais espertos para trabalhar num projeto com Python do que se conseguiria para trabalhar num projeto com Java.

Eu não quis dizer com isso que programadores Java são burros. O que eu quis dizer é que programadores Python são espertos. Dá muito trabalho aprender uma nova linguagem de programação. E as pessoas não aprendem Python porque ela vá lhes garantir um trabalho; elas a aprendem pois genuinamente gostam de porgramar e não estão satisfeitas com as linguagens de programação que elas já conhecem.

Isso faz dessas pessoas exatamente o tipo de programadores que as empresas deveriam estar interessadas em contratar. Daí que, por falta de um nome melhor, eu vou chamar de “O Paradoxo Python”: se uma empresa escolhe escrever seu software numa linguagem comparativamente esotérica, ela vai ter a possibilidade de contratar programadores melhores, pois ela vai atrair somente aqueles que se interessaram/preocuparam o suficiente para aprender anteriormente a linguagem. E no caso dos programadores o paradoxo é ainda mais pronunciado: a linguagem a se aprender, se você quer conseguir um emprego, é a linguagem que as pessoas não apredem somente para conseguir um emprego.

Apenas poucas companhias tem sido espertas o suficiente para perceber isso até agora. Mas existe um tipo de seleção acontecendo nesse caso também: essas são exatamente as empresas para as quais os programadores gostariam mais de trabalhar. O Google, por exemplo. Quando eles fazem chamadas para empregos para programção em Java, eles também querem e pedem experiência em Python.

Um amigo meu que sabe quase todas as linguagens de programação amplamente usadas usa Python para a maioria dos seus projetos. Ele diz que a razão principal é que ele gosta do jeito que o código fonte fica [quão bonito ele fica]. Essa pode parecer uma razão frívola para se escolher uma linguagem de programação em relação a outra. Mas não é tão frívola quanto parece: quando você programa, você passa bem mais tempo lendo código do que escrevendo. Você move pedaços de código de um lado para o outro como um escultor faz com pedaços de argila. Então uma linguagem de programação que faça com que o código fique feio é enlouquecedora para um programador exigente, assim como argila cheia de protuberâncias seria para um escultor.

A mera menção de código fonte “feio”, muitas pessoas vão logo obviamente pensar em Perl. Mas a feiura superficial de Perl não é o tipo de feiura ao qual me refiro. Feiura de verdade não é a sintaxe áspera ao olhar(harsh-looking), mas sim ter que construir programas a partir dos conceitos errados. Perl pode parecer com um personagem de desenho animado xingando, mas existem casos onde Perl é até mesmo melhor que Python conceitualmente.

Até agora, pelo menos. Ambas as linguagem obviamente são alvos móveis. Mas elas compartilham, assim como com Ruby (e Icon, e Joy, e J, e Lisp, e Smalltalk), o fato que elas foram criadas por, e usadas por, pessoas realmente interessadas em programação. E estas linguagem são as que tendem a fazer o serviço melhor.

Read Full Post | Make a Comment ( None so far )

Convertendo um excel xls em table HTML usando python

Posted on 23 \d\e dezembro \d\e 2010. Filed under: computers, python | Tags:, , , , , , , , |

import xlrd
from lxml.html import builder as E, tostring
from lxml.etree import ElementTree

def itermeth(obj, method, endattr):
    for index in xrange(getattr(obj, endattr)):
        yield getattr(obj, method)(index)

def xls_tree(xls_filename, header=True, tableattrs=None):
    if tableattrs is None:
        tableattrs = {}
    workbook = xlrd.open_workbook(xls_filename)
    head = E.HEAD(E.TITLE(xls_filename))
    body = E.BODY()
    for sheet in workbook.sheets():
        if sheet.nrows <= 0 or sheet.ncols <= 0:
            continue # sheet is empty
        table = E.TABLE(E.CAPTION(sheet.name), **tableattrs)
        container = E.THEAD()
        table.append(container)
        cellClass = E.TH
        for xlsrow in itermeth(sheet, 'row', 'nrows'):
            row = E.TR()
            container.append(row)
            if header:
                container = E.TBODY()
                table.append(container)
                cellClass = E.TD
                header = False
            for cell in xlsrow:
                row.append(cellClass(unicode(cell.value)))
        body.append(table)
    return ElementTree(E.HTML(head, body))
    

## Example usage:
html = xls_tree('/home/nosklo/Documentos/teste.xls', 
    tableattrs={'class': 'mytable', 'border': '2'})
# print to screen
print tostring(html, pretty_print=True)
# write to file
html.write('/tmp/resultado.html')
Read Full Post | Make a Comment ( 2 so far )

Problema da soma de sub-ítens

Posted on 19 \d\e janeiro \d\e 2010. Filed under: python | Tags:, , , , , , , , , |

Estes dias estava desenvolvendo um programa de conciliação contábil quando me deparei com um problema de programação, no trampo. Passei o programa no canal #python-br e estamos tentando resolvê-lo da forma que tenha mais performance.

Achei muito interessante o fato de conseguir envolver a todos, muita gente está tentando escrever o algoritmo.

O problema consiste em fazer um algoritmo que ao receber uma lista de números inteiros, retorne uma sublista cuja soma é zero.

Porém, tem os seguintes modificadores:

  • Caso não exista nenhuma sublista que alcance zero, a lista vazia deverá ser retornada.
  • Caso exista mais de uma sublista que some zero, o algoritmo deve encontrar aquela que tem o maior valor absoluto, ou seja, o maior valor desconsiderando o sinal (módulo).
  • Em caso de empate, qualquer uma das combinações pode ser retornada.

Nada como alguns exemplos para entender melhor:

  • Para a lista [-5, -3, 10, 16] não tem nenhuma sublista que dê zero, então o algoritmo deve retornar a lista vazia []
  • No caso da lista [-5, -3, 3, 10] o algoritmo deve calcular a sublista [-3, 3] (cuja soma dá 0).
  • Porém, se a lista é [-15, -3, 3, 18] o algortmo tem duas possibilidades cuja soma é zero:
    • retornar [-3, 3] (soma 0)
    • retornar [-15, -3, 18] (soma 0)
  • Quando isso ocorrer, o algoritmo deve estar montado de forma a retornar a sublista com maior valor absoluto, ou seja, [-15, -3, 18] (soma absoluta 36).

Após intensiva pesquisa, encontrei isto na wikipedia. O problema é da classe NP-Hard, e não existe solução linear. Porém com uma linguagem dinâmica, é possível fazer soluções pseudo-polinomiais.

O que estou procurando é justamente este algoritmo otimizado.

Resolvi desenvolver primeiramente o programa de referência. Este programa encontra a solução do problema através da força bruta, ou seja, gera todas as possibilidades de combinações existentes, soma cada uma pra encontrar as combinações cuja soma é zero, e depois verifica qual delas é a que tem maior valor absoluto. A resposta deste código sempre está correta, porém, o tempo para gerar todas as possibilidades é quadrático e dobra a cada novo ítem acrescentado na lista.

Aqui está o programa de referência:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright © 2010 Clóvis Fabrício Costa
# Licensed under GPL version 3.0 or higher 

from itertools import chain, combinations

def acha_combinacao(itens):
    """
    Função que resolve o problema "subset sum" através da geração de todas
    as possibilidades.
    
    Passe uma lista de números inteiros, e a função retornará uma sublista
    cuja soma é zero. 
    
    Caso não exista nenhuma sublista que alcance zero, a lista vazia será
    retornada.
    
    Caso exista mais de uma sublista que tem zero, o algoritmo deve encontrar
    aquela que tem o maior valor absoluto, ou seja, o maior valor 
    desconsiderando o sinal (módulo).
    
    Em caso de empate, qualquer uma das combinações pode ser retornada.
    """
    # gera todas as combinações possíveis
    todas_combs = chain.from_iterable(combinations(itens, n+1)
                                   for n in xrange(len(itens)))
    # procura a maior
    maior_comb = []
    maior_somaabs = 0
    for comb in todas_combs:
        if sum(comb) != 0:
            continue # Combinação não dá zero, pulando.
        somaabs = sum([abs(item) for item in comb])
        if somaabs > maior_somaabs:
            maior_comb = comb
            maior_somaabs = somaabs
    return maior_comb

Para quem quiser tentar fazer o seu algoritmo, estou disponibilizando em meu repositório o programa de referência acima, todas as minhas tentativas até agora, um arquivo de dados contendo números para teste com a respectiva resposta correta, e um programa que lê este arquivo de dados e testa a sua função automaticamente. Desta forma fica fácil achar os problemas do código.

A versão disponibilizada no repositório é compatível com versões do python < 2.6 (o código acima não é).

O repositório está hospedado no bitbucket, e pode ser baixado utilizando o mercurial, com o seguinte comando:

hg clone http://bitbucket.org/nosklo/subset_sum

Para testar seu código, coloque seu arquivo contendo o código na mesma pasta onde você baixou o repositório acima e use o seguinte modelo:

1
2
import referencia
referencia.teste(sua_funcao)

Isso é o suficiente. A sua função será testada com todos os dados de teste que gerei, e vai mostrar qualquer erro encontrado nos resultados.

Qualquer dúvida, estou no canal #python-br da freenode. Muito obrigado a todos que estão ajudando a encontrar este algoritmo.

Read Full Post | Make a Comment ( None so far )

Traduzindo pylons book

Posted on 15 \d\e dezembro \d\e 2009. Filed under: python | Tags:, , , , , , , , , |

Iniciando trabalho de tradução do pylonsbook pra Português do Brasil! Alguém pode dar uma força?

O livro está na Gnu FDL. O primeiro passo é arrumar o fonte do livro.

O renatopp já criou um projeto aqui pra gente publicar a tradução.

Read Full Post | Make a Comment ( 1 so far )

twisted 9.0 pré

Posted on 24 \d\e novembro \d\e 2009. Filed under: computers, python | Tags:, , , , , , |

Saiu o twisted 9 pre-release!

\o/

Vamos testar enquanto ainda está quente!!

Download aqui.

Read Full Post | Make a Comment ( None so far )

Definição de estrutura de diretórios de projetos python

Posted on 12 \d\e novembro \d\e 2009. Filed under: computers, irc, python |

Uma dúvida que sempre surge é como definir a estrutura de pastas para um novo projeto. Eu sempre sigo estas dicas que vou passar agora, pois elas permitem uma grande facilidade de instalar, testar e distribuir o código, e assegura que ele se comportará corretamente em todas as plataformas.

  • Crie uma pasta para seu projeto. Por exemplo, se seu projeto se chama NetoChat, crie uma pasta NetoChat para ser a raiz do seu projeto. Quando você lançar uma versão, inclua um sufixo de versão: NetoChat-2.5
  • Crie dentro desta pasta um pacote python para conter o fonte do seu projeto. Dê a ela um nome sem traços e sem espaços, somente com letras minúsculas. Exemplo: NetoChat/netochat. Crie um arquivo __init__.py vazio dentro desta pasta para que ela seja considerada um pacote. NetoChat/netochat/__init__.py
  • Coloque seus módulos lá dentro do pacote: NetoChat/netochat/interface.py NetoChat/netochat/rede.py
  • Você também pode organizar em subpacotes. Primeiro crie NetoChat/netochat/eventos/__init__.py para criar um pacote eventos. Em seguida crie seus módulos lá dentro, por exemplo, NetoChat/netochat/eventos/som.py Fazendo desta forma, estes módulos podem ser chamados facilmente de forma absoluta, sem ambiguidades nem confusões. Exemplos:
    • from netochat.eventos import som
    • from netochat import rede
  • Crie uma pasta NetoChat/bin onde você colocará seus executáveis. Estes executáveis devem ser scripts python sem a extensão .py, que possuem somente uma linha importando e executando uma função que deve estar definida em outro ponto do projeto. Não coloque o código em si nestes scripts, apenas a chamada. Exemplo, NetoChat/bin/nchat:
    • from netochat.interface import main_window ; main_window()
  • Ponha seus testes de unidade em um outro pacote python. Mais uma vez, isto implica em criar o pacote (NetoChat/tests/__init__.py)  e colocar seus testes lá (NetoChat/tests/test_rede.py, NetoChat/tests/test_interface.py)
  • Adicione alguns arquivos que é sempre bom ter:
    • NetoChat/setup.py – programa de instalação criado com distutils para instalar seu programa e registrá-lo automaticamente;
    • NetoChat/README – descrição do seu programa;
    • NetoChat/LICENSE – licença de distribuição do seu código;
    • NetoChat/TODO, NetoChat/INSTALL, etc

A estrutura do código ficaria assim:

  • NetoChat/
    • setup.py
    • README
    • bin/
      • nchat
    • netochat/
      • __init__.py
      • interface.py
      • rede.py
      • eventos
        • __init__.py
        • som.py
      • tests/
        • __init__.py
        • test_interface.py
        • test_rede.py

Por favor, não faça, repito, não faça as coisas abaixo:

  • NÃO coloque seu código fonte em uma pasta chamada lib ou src – dificulta a execução do seu código sem instalá-lo.
  • NÃO ponha seus testes fora do pacote python principal do seu projeto – dificulta a execução dos testes em uma versão instalada do código
  • NÃO crie um pacote com apenas um __init__.py e ponha o código todo em __init__.py. Simplesmente crie um módulo comum ao invés de um pacote. É mais simples.
  • NÃO tente criar gambiarras e usar magia negra para fazer seu módulo ser importável sem que o usuário tenha que adicioná-lo ao caminho de importação dele (através de PYTHONPATH, setup.py ou qualquer outro mecanismo). Você com certeza vai deixar algo faltando e seu programa não vai rodar em alguma plataforma ou caso específico se você tentar assim. Simplesmente crie o setup.py usando distutils e ele fará a coisa certa automaticamente.

Leia em seguida a conversa de irc que deu origem a este post (uma das muitas vezes que respondi essa dúvida):

(mais…)

Read Full Post | Make a Comment ( 1 so far )

Código no escopo global

Posted on 20 \d\e outubro \d\e 2009. Filed under: python | Tags:, , , , |

Todo mundo parece achar que colocar código diretamente no escopo superior (global) de um módulo python é legal. Eu não ligo, só peço que, se você fizer isso, não me faça usar o programa resultante. Mais especificamente, não me faça usar frameworks ou bibliotecas que cheguem a depender deste comportamento.

Afinal, tem um motivo pelo qual todo livro de Python que se preze, no primeiro capítulo, coloca uma cláusula desta forma:

if __name__ == '__main__':
   # do stuff

Isto permite a execução desta parte do módulo como um script, mas impede a execução caso o módulo seja importado por outro módulo. Todo script pode no futuro ser importado por outro módulo, e como o autor do módulo parece não querer que o código dentro do bloco “if” seja executado neste caso, faz sentido colocar tudo que não faz parte da inicialização do próprio módulo dentro de uma cláusula destas.

__name__ é uma variável definida automaticamente pelo interpretador, que recebe o valor '__main__' quando o script atual é o que foi iniciado no interpretador. Para scripts importados, __name__ é o nome de importação do script. Essa diferença permite escrever código que execute condicionado ao módulo ter sido importado ou executado.

Importar um módulo deve fazer no máximo estas coisas:

  • Importar outros módulos ou globais
  • Atribuir valores constantes a variáveis
  • Adicionar novas funções usando a cláusula def
  • Adicionar novas classes usando a cláusula class
  • Fluxo de controle que pode controlar partes condicionais do módulo para tratar erros ou versões específicas de certas plataformas para os casos acima.

Qualquer outro tipo de lógica executada direto no corpo de um módulo python (código que roda automaticamente durante imports) é tratado com suspeita e provavelmente está no lugar errado.

É um absurdo construir um sistema que se inicia ou se configura baseado em efeitos colaterais da importação de módulos. Você perde o controle de quando o código será executado. Ferramentas de inspeção automática de código, geração de documentação e de testes muitas vezes precisam importar o módulo para efetuar suas tarefas, e isto causa efeitos indesejados.

Read Full Post | Make a Comment ( None so far )

ajuste a água conforme o foobar

Posted on 3 \d\e março \d\e 2009. Filed under: irc, python | Tags:, , , , |

Geralmente uma simples conversa de IRC gera um projeto. Desta vez foi o meu iconv_codecs, um módulo python para encodificação e decodificação usando os codecs definidos pelo GNU iconv. Leia aqui a conversa na íntegra:

(mais…)

Read Full Post | Make a Comment ( 4 so far )

Licenciamento

Posted on 2 \d\e março \d\e 2009. Filed under: irc, licenciamento, python | Tags:, , , , , |

Estava hoje cedo no irc e tive uma conversa interessante sobre licenciamento e ganhar dinheiro com programas python e opensource.
Coloco aqui a conversa na íntegra.

(mais…)

Read Full Post | Make a Comment ( 2 so far )

  • Blog Stats

    • 6.066 hits
  • contribua!

Liked it here?
Why not try sites on the blogroll...