iteradores.

Joaquin Jose del Cerro Murciano jjdelcerromurciano en yahoo.es
Sab Mayo 21 23:27:05 CEST 2005


Holas,

Ya estoy aqui de nuevo de vueltas con mi problema con los iteradores.

Despues de los  mensajes de Hernan Martinez, que han sido mi inspiracion, creo 
que puedo tener una solucion a mi problema de la clase SynchronizedDict, 
aunque aun me queda una duda. Basicamente uso un objeto a modo de wrapper 
sobre el iterador, que me bloquea el diccionario al iniciar la iteracion y lo 
desbloquea al destruirse el wrapper. Pero la clase esta tiene el metodo 
__del__, y siempre me ha dado bastante miedo meterle este metodo a alguna 
clase, ya que segun he entendido cuando una clase tiene este metodo y se da 
una referencia circular en la que interviene un objeto de esta clase, la 
referencia circular entera no es liberada por el recolector de basura. A 
pesar de eso no creo que en este caso se vayan a dar este tipo de problemas. 

Pego aqui el codigo y si alguien le ve algo raro agradeceria sus comentarios, 
y si no, pues aqui esta para el que lo quiera gastar.

Tambien agradeceria cualquier correccion sobre el mi interpretacion del metodo 
__del__ y las referencias circulares.

Tampoco tengo claro que metodos deberia implementar en mi clase wrapper sobre 
el iterador. Los que he puesto a sido a base de construir un iterador y mirar 
que tenia, y a partir de ahi ver a que se llamaba y que podia devolver yo. 
Vamos prueba y error basicamente. Si alguien ve que deberia implementar algo 
mas sobre el wrapper, no estaria mal que lo comentase.

Bueno, gracias por adelantado, y aqui dejo el codigo.

from threading import RLock

class LockIterator(object):
    def __init__(self,iter,lock):
        self.__lock = lock
        self.__iter = iter
        self.__needlock = True

    def __del__(self):
        if not self.__needlock:
            print "__del__: desbloqueo"
            self.__lock.release()

    def next(self):
        if self.__needlock:
            print "next: Bloqueo"
            self.__lock.acquire()
            self.__needlock = False
        return self.__iter.next()

    def __iter__(self):
        if self.__needlock:
            print "__iter__: Bloqueo"
            self.__lock.acquire()
            self.__needlock = False
        for value in self.__iter:
            yield value


class SynchronizedDict(dict):
    def __init__(self):
        dict.__init__(self)
        self._lock = RLock()

    def acquire(self):
        return self._lock.acquire()

    def release(self):
        return self._lock.release()

    def __len__(self):
        try:
            self._lock.acquire()
            return dict.__len__(self)
        finally:
            self._lock.release()
    
    def __setitem__(self,key,value):
        try:
            self._lock.acquire()
            dict.__setitem__(self,key,value)
        finally:
            self._lock.release()

    def __getitem__(self,key):
        try:
            self._lock.acquire()
            return dict.__getitem__(self,key)
        finally:
            self._lock.release()

    def get(self,key,default=None):
        try:
            self._lock.acquire()
            return dict.get(self,key,default)
        finally:
            self._lock.release()

    def __delitem__(self,key):
        try:
            self._lock.acquire()
            dict.__delitem_(self,key)
        finally:
            self._lock.release()

    def __iter__(self):
        return LockIterator(dict.__iter__(self),self._lock)

    def iterkeys(self):
        return LockIterator(dict.iterkeys(self),self._lock)

    def iteritems(self):
        return LockIterator(dict.iteritems(self),self._lock)

    def itervalues(self):
        return LockIterator(dict.itervalues(self),self._lock)


def test():
    x = SynchronizedDict()
    x["a"] = 1
    x["b"] = 2
    x["c"] = 3
    print "Inicio 1, iteritems"
    for n in x.iteritems():
        print n
    print "Fin 1"
    print "Inicio 2, x"
    for n in x:
        print n
    print "Fin 2"
    try:
        print "Inicio 3, __iter__ + pete"
        for n in x.__iter__():
            print n
            1/0
        print "Fin 3"
    except:
        print "Ha petao"

if __name__ == "__main__":
    test()


"""
Inicio 1, iteritems
__iter__: Bloqueo
('a', 1)
('c', 3)
('b', 2)
__del__: desbloqueo
Fin 1
Inicio 2, x
next: Bloqueo
a
c
b
__del__: desbloqueo
Fin 2
Inicio 3, __iter__ + pete
__iter__: Bloqueo
a
__del__: desbloqueo
Ha petao
"""

Un saludo 
Joaquin.




Más información sobre la lista de distribución Python-es