martes, 22 de febrero de 2011

Haciendo un iterador a medida en Python

Mientras no van llegando cosas que requiren más tiempo aquí va algo que puede resultar interesante, vamos a hacer nuestro propio iterador dinámico, que permita modificar su comportamiento desde el propio script, por ejemplo, si hacemos:

for i in my_iterator(1,1000,"<<1"):
    print i


my_iterator( inicio, límite, paso ) Mostraría esto:

1
2
4
8
16
32
64
128
256
512


La idea es bastante simple, necesitamos una clase que sirva de iterador, necesita 2 métodos [ tipos - iterador ]:
__iter__(): que devuelve un iterador ( un objeto que tenga el siguiente método ), por pura pereza, en este ejemplo se devolverá a si mismo ( self )
next(): este es el método del iterador, muestra el siguiente valor o levanta StopIteration

Si vamos escribiendo la clase, el __iter__ y __init__ iría así:

class my_iterator:

    def __iter__(self):
        return self

    def __init__(self, init,end,expr):
        self.nextVal=init
        self.end =end
        self.expr=expr


Y atención que ahora viene el juego de manos!, para interpretar dinámicamente el argumento paso, utilizaremos exec() [ exec ] , que se ejecuta en el entorno local, y que permite ejecutar código desde un string:

    def next(self):
        self.curr = self.nextVal
        exec("self.nextVal = "+str(self.curr)+" "+self.expr)
        if (self.curr != None)and( self.curr < self.end ):
            return self.curr
        else:
            raise StopIteration


Mete el valor actual en self.curr (valor que se devolverá) y asigna self.nextVal al siguiente valor( en ese exec está el truco ).

Y eso es todo, saludos

No hay comentarios:

Publicar un comentario