About me

About

2014-07-13

Pythonices, classes ou funções.

Eu uso algumas regras simples para decidir entre usar classes ou funções, em python:

  • se existe necessidade de manter estado: classes;
  • caso contrário: funções;
  • para agrupar informação relacionada, tuples ou namedtuples.

2014-07-02

Configurações.

Algumas configurações pouco comuns mas muito úteis.

  1. Num ambiente X ter teclas e rato rápidos… mas não demais.

    xset m 1
    xset r rate 220 80

    A segunda faz-me bastante falta, e é um efeito que não se consegue obter em Windows (excepto eventualmente se se usarem truques não triviais).

  2. Cores para ecrãs de texto: letras verdes em fundo preto.

    Costumava usar um simples green/black (testar=> xterm -fg green -bg black), mas os novos ecrãs de LED IPS têm um contraste muito maior, o que torna o “green” muito mais brilhante do que estava habituado.

    Após alguma pesquisa, o chamado “kelly green” (fonte: wikipedia) provou ser o melhor verde para este tipo de painéis de alto contraste.

    xterm -fg #4CBB17 -bg black
  3. Fontes mono-espaçadas para terminais e desenvolvimento: DejaVu Sans Mono Book.

    Atenção à semelhança entre alguns caracteres. Ver se os seguintes são suficientemente diferentes para serem facilmente distinguidos:

    i1lI O0

    Em particular gosto que o zero tenha algo no meio (risco, ponto) e que o “l” pequeno faça uma curvinha pelo menos em baixo.

    A fonte “DejaVu Sans Mono Book” tem representações suficientemente diferentes. Outras boas alternativas:

    • Liberation Mono
    • Inconsolata

    Bom exemplo: bom exemplo

    Mau exemplo: mau exemplo

2014-06-29

Pythonices, throttling.

Problema: precisamos de executar uma acção sujeita a limites temporais, não mais que n execuções por segundo são permitidas. Chamemos a isto throttle.

Como boa prática a função de throttle deve estar separada da acção f a executar. Uma abordagem funcional é perfeita: f = throttle(count, timeframe, f), tal que a função retornada por throttle() tenha o mesmo inteface que f.

Isto é precisamente o que fazem os decoradores em python.

Eis a minha implementação desta funcionalidade.

import datetime

def throttle(count, timeframe):  # timeframe in seconds
    def work(fn):
        # state is lasttimemarker, remaining count
        state = [datetime.datetime.now(), count]

        def __work(*args, **kwargs):
            elapsed = datetime.datetime.now() - state[0]
            ntimeframes = int(elapsed.total_seconds() // timeframe)
            if ntimeframes > 0: ## just an optimization
                state[1] += count * ntimeframes
                state[0] += datetime.timedelta(seconds=timeframe) * ntimeframes
            if state[1] <= 0:
                wait_time = timeframe - elapsed.total_seconds() % timeframe
                time.sleep(wait_time)
                return __work(*args, **kwargs)
            state[1] -= 1
            rv = fn(*args, **kwargs)
            return rv
        return __work
    return work

####

import time

# exec 3 times on each 5 seconds timeframe
@throttle(3, 5)
def printtime():
    print time.ctime(time.time())
    
for i in range(10): printtime()
Sat Jun 28 17:16:08 2014
Sat Jun 28 17:16:08 2014
Sat Jun 28 17:16:08 2014
Sat Jun 28 17:16:13 2014
Sat Jun 28 17:16:13 2014
Sat Jun 28 17:16:13 2014
Sat Jun 28 17:16:18 2014
Sat Jun 28 17:16:18 2014
Sat Jun 28 17:16:18 2014
Sat Jun 28 17:16:23 2014

2014-06-28

Pythonices, enumerate.

Uma idiossincrasia comum em python é iterar com ciclos for.

xs = "a b c d".split()
for x in xs:
    print x
a
b
c
d

Mas por vezes é necessário ter um contador associado. A solução mais imediata é manter um contador à parte e incrementá-lo dentro do loop. Por vezes é necessário trocar o for por um while.

Felizmente existe uma construção nativa que permite associar uma contagem a qualquer iterador: enumerate.

xs = "a b c d".split()
for i,x in enumerate(xs):
    print i,x
0 a
1 b
2 c
3 d

O enumerate é a aplicação de uma técnica comum em linguagens funcionais: transformar uma lista de valores (escalares) numa lista de tuples, juntando a informação adicional no outro membro do tuple.

Repare-se que o enumerate corresponde à aplicação de duas funções do módulo itertools.

import itertools
xs = "a b c d".split()
for i,x in itertools.izip(itertools.count(), xs):
    print i,x
0 a
1 b
2 c
3 d