with tutorial the español applications python list python-3.x iterable

python - tutorial - ¿Cómo hacer iterable un objeto personalizado?



the django project (3)

También puede hacer una list subclase:

class Direction(list): def __init__(self, seq=[], id_=None): list.__init__(self,seq) self.id = id_ if id_ else id(self) def __iter__(self): it=list.__iter__(self) next(it) # skip the first... return it d=Direction(range(10)) print(d) # all the data, no iteration # [0, 1, 2, 3, 4] print ('', ''.join(str(e) for e in d)) # ''for e in d'' is an iterator # 1, 2, 3, 4

es decir, se salta el primero.

Funciona también para listas anidadas:

>>> d1=Direction([range(5), range(10,15), range(20,25)]) >>> d1 [range(0, 5), range(10, 15), range(20, 25)] print(list(itertools.chain.from_iterable(d1))) [10, 11, 12, 13, 14, 20, 21, 22, 23, 24]

Tengo una list de objetos personalizados (la muestra está debajo).

Usando: list(itertools.chain.from_iterable(myBigList)) Quería "fusionar" todas las sublistas de stations en una gran lista. Así que pensé que necesitaba hacer que mi clase personalizada fuera iterable.

Aquí hay una muestra de mi clase personalizada.

class direction(object) : def __init__(self, id) : self.id = id self.__stations = list() def __iter__(self): self.__i = 0 # iterable current item return iter(self.__stations) def __next__(self): if self.__i<len(self.__stations)-1: self.__i += 1 return self.__stations[self.__i] else: raise StopIteration

Implementé __iter__ y __next__ pero parece que no funciona. Ni siquiera son llamados.

¿Alguna idea de lo que podría haber hecho mal?

Nota: Usando Python3.3


simplemente implementar __iter__ debería ser suficiente.

class direction(object) : def __init__(self, id) : self.id = id self.__stations = list() def __iter__(self): #return iter(self.__stations[1:]) #uncomment this if you wanted to skip the first element. return iter(self.__stations) a = direction(1) a._direction__stations= range(5) b = direction(1) b._direction__stations = range(10) import itertools print list(itertools.chain.from_iterable([a,b])) print list(itertools.chain.from_iterable([range(5),range(10)]))

salida:

[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Vea aquí por qué es _direction__stations

Cualquier identificador del formulario __spam (al menos dos guiones bajos principales, como máximo un guión bajo final) se reemplaza textualmente por classname _spam, donde classname es el nombre de clase actual con guiones bajos destacados.


__iter__ es lo que se llama cuando intenta iterar sobre una instancia de clase:

>>> class Foo(object): ... def __iter__(self): ... return (x for x in range(4)) ... >>> list(Foo()) [0, 1, 2, 3]

__next__ es lo que se llama en el objeto que se devuelve desde __iter__ (en python2.x, es el next , no __next__ - Generalmente los __next__ a ambos para que el código funcione con cualquiera de ...):

class Bar(object): def __init__(self): self.idx = 0 self.data = range(4) def __iter__(self): return self def __next__(self): self.idx += 1 try: return self.data[self.idx-1] except IndexError: self.idx = 0 raise StopIteration # Done iterating. next = __next__ # python2.x compatibility.