quarta-feira, 20 de julho de 2016

Classes Abertas em Python

Em python é possível adicionar métodos e atributos nas classes mesmo depois de já definidas.
class Person(object):
  def __init__(self,name):
    self.name = name

p = Person('programando no aquario')
print p.name
print p

def person_str(self):
  return self.name

Person.__str__ = person_str

print p

def print_hello(self):
  print 'Hello %s' % self.name

Person.hello = print_hello

p.hello()


Assim é possível adicionar algum comportamento a classes de bibliotecas de terceiros sem alterar o código da biblioteca, ou mudar de forma dinâmica o comportamento das classes.

Obrigado!

segunda-feira, 18 de julho de 2016

Python @decorator

Decorators em Python lembram muito as anotações do Java, pelo menos em sua sintaxe.

Os decorators são funções que recebem uma classe ou uma função e retornam algo para substituir a classe ou a função que receberam.
Assim é possível mudar todo o comportamento da função ou da classe, simplesmente a substituindo por outra coisa, ou adicionar comportamento ao comportamento padrão.

def soma(a,b):
  return a + b

print soma(5,5)


O código acima é um exemplo simples de uma função de soma. Agora vamos criar um decorator que realizará um log da execução desta função.
def log_decorator(func):
  def new_func(a,b):
    print 'Executando: %s(%d,%d)' % (func.__name__,a,b)
    result = func(a,b)
    print 'Resultado: %d' % result
    return result

  return new_func


@log_decorator
def soma(a,b):
  return a + b

print soma(5,5)


Nesse exemplo foi adicionado o comportamento de log a função. Agora neste o decorator será utilizado para alterar o comportamento original.
def mult_decorator(func):
  def new_func(a,b):
    return a * b
  
  return new_func

@mult_decorator
def soma(a,b):
  return a + b

print soma(5,5)


Esse último exemplo não é muito usual, mas demonstra bem o potencial que os decorators podem ter.

Decorators podem adicionar atributos a classes, mudar suas funções entre outras coisas mais. Os decorators também podem ser classes que implementem o método __call__ para poderem se comportar como funções, dessa forma é possível parametrizar os decorators.
class AddDecorator(object):
  def __init__(self,val):
    self.func = None
    self.val = val

  def __call__(self,func):
    self.func = func
    return self.decorator

  def decorator(self,a,b):
    return self.func(a,b) + self.val

@AddDecorator(-10)
def soma(a,b):
  return a + b

print soma(5,5)


Obrigado!

sexta-feira, 15 de julho de 2016

Python List Comprehensions

List Comprehensions é uma maneira enxuta para criar listas em Python.
Basicamente é necessário escrever uma pequena regra que gere a lista entre [ ].

# resulta em [ 0 ** 2, 1 ** 2, 2 ** 2, ... ,9 ** 2]
print [ x ** 2 for x in range(10)]

# resulta em ['','a','aa', ..., 'aaaaaaaaa']
print [ 'a' * x for x in range(10)]

# resulta em [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
print [ sum(range(0,x+1)) for x in range(10) ]

# resulta em [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
print [ x for x in range(20) if x % 2 == 0 ]


Obrigado!

quarta-feira, 13 de julho de 2016

Python Yield

Com yield é possível criar iteradores de maneira simples e eficiente.
Ao invés de utilizar memória para armazenar uma lista com valores para serem iterados, com yield fica fácil gerar os valores conforme a necessidade.

# gera potencias de 2
def pot2(limit=None):
    i = 0
    while limit is None or i < limit:
        yield 2**i
        i += 1

# imprime um generator
print pot2(10)

# imprime uma lista com os
# valores fornecidos pelo generator
print list(pot2(10))

# generator infinito limitado
# pelo range
g = pot2()
for i in range(5):
    print g.next()

# percorre os valores do generator
for v in pot2(10):
    print v



Obrigado!