Durante o curso discutimos um pouco sobre implementação dos chamados ‘métodos mágicos’ de python. Ao invés de interfaces, python adota protocolos a serem seguidos para que objetos criados por você programador obedeça alguns comportamentos, e é por ai que python implementa polimorfismo.
Vejamos por exemplo a função len():
>>> string = ‘flavio’
>>> len(string)
6
>>> lista = ['flavio',21,'ifpb']
>>> len(lista)
3
Ela tem a capacidade de retornar o tamanho de um objeto, mas não de qualquer objeto:
>>> a = 3
>>> len(a)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: object of type ‘int’ has no len()
Se você quiser que seu próprio objeto consiga retornar o tamanho ou comprimento de algo pela função len() basta você escrever o método mágico __len__ na sua classe. Imagine que você tem uma classe Pessoa e quer saber a altura das pessoas através do len():
>>> class Pessoa(object):
… def __init__(self, altura=0):
… self.altura = altura
… def __len__(self):
… return self.altura
…
>>> Flavio = Pessoa(184)
>>> len(Flavio)
184
Legal, né? Agora, pra não fugir muito o escopo desse post, vamos aos iteradores. Um iterador é basicamente um objeto que pode ser incrementado e decrementado, ser ‘percorrido’. A palavra iterar significa repetir algo algumas vezes. No python 3 uma função muito utilizada nos laços for, a range(), que antes retornava uma lista (que por sua vez é iteravel) nas versões 2.x agora se comporta como a antiga xrange(), retornando um objeto em si que tem a capacidade de iterar.
No Python 2.X:
>>> type(xrange(3))
<type ‘xrange’>
>>> type(range(3))
<type ‘list’>
No Python 3000 (Py3k, Python 3):
>>> type(range(10))
<class ‘range’>
>>> xrange(10)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
NameError: name ‘xrange’ is not defined
Sabendo já sobre métodos mágicos e o que são iteradores chegou a hora de criar um iterador mesmo, na real. Para você ter um iterador, basta que você crie um método mágico chamado __iter__() retornando a própria instância e um outro método chamado next(), onde as coisas vão realmente acontecer a cada iteração.
Como sou péssimo com exemplos vou simplificar e criar apenas uma classe que gera a velha conhecida dos programadores, ou pelo menos das pessoas que pagaram introdução aos algoritmos: Fibonacci.
class Fibonacci(object): def __init__(self): self.a = 0 self.b = 1 def __iter__(self): return self def next(self): self.a, self.b = self.b, self.a+self.b return self.a
Pronto, agora podemos iterar em cima do nosso proprio objeto!
>>> fib = Fibonacci()
>>> for num in fib:
… if num < 150:
… print num,
… else:
… break
…
1 1 2 3 5 8 13 21 34 55 89 144
Sim, e esse plugin de colorir sintaxe já tá me irritando, engoliu a identação, quebras de linha e etc. Quem usar algum plugin melhor favor me avisar nos comentários!


