Pregunta

A pesar de leerlo, todavía no entiendo bien cómo funciona __iter__ . ¿Cuál sería una explicación simple?

He visto def__iter __ (self): return self . No veo cómo funciona esto o los pasos sobre cómo funciona esto.

¿Fue útil?

Solución

Un iterador debe definir dos métodos: __iter __ () y __next __ () ( next () en python2). Por lo general, el objeto en sí define el método __next __ () o next () , por lo que simplemente se devuelve a sí mismo como el iterador. Esto crea un iterable que también es un iterator . Estos métodos son utilizados por para y en las declaraciones de .

Otros consejos

Tan simple como puedo decirlo:

__iter__ define un método en una clase que devolverá un iterador (un objeto que produce sucesivamente el siguiente elemento contenido por su objeto).

El objeto iterador que devuelve __iter __ () puede ser prácticamente cualquier objeto, siempre que defina un método next () .

El método next será llamado por declaraciones como para ... en ... para obtener el siguiente elemento, y next () debe aumentar la excepción StopIteration cuando no haya más elementos.

Lo bueno de esto es que le permite a usted definir cómo se itera su objeto, y __iter__ proporciona una interfaz común con la que todas las demás funciones de python saben cómo trabajar.

Las especificaciones para def __iter __ (self): son: devuelve un iterador. Por lo tanto, si self es un iterador, return self es claramente apropiado.

" Ser un iterador " significa " que tiene un método __siguiente __ (auto) " (en Python 3; en Python 2, el nombre del método en cuestión es, desafortunadamente, simple next , claramente un problema de diseño de nombre para un método especial).

En Python 2.6 y versiones posteriores, la mejor manera de implementar un iterador es generalmente usar la clase base abstracta apropiada de la biblioteca estándar colecciones module - en Python 2.6, el código podría ser (recuerde llamar al método __next__ en lugar de Python 3):

import collections

class infinite23s(collections.Iterator):
  def next(self): return 23

una instancia de esta clase devolverá infinitas copias de 23 cuando se repita (como itertools.repeat (23) ), por lo que el ciclo debe terminarse de otro modo. El punto es que la subclase de collections.Iterator agrega el método correcto __iter__ en su nombre, no es un gran problema aquí, pero es un buen principio general (evite el código repetitivo y repetitivo como __iter__ de una línea estándar de los iteradores - en repetición, no hay valor agregado y mucho valor restado! -).

Una clase que admita el método __iter__ devolverá una instancia de objeto iterador: un objeto que admita el método next () . Este objeto se podrá utilizar en las declaraciones " para " y " en " ;.

En Python, un iterador es cualquier objeto que admita el protocolo del iterador. Parte de ese protocolo es que el objeto debe tener un método __iter __ () que devuelva el objeto iterador. Supongo que esto le da cierta flexibilidad para que un objeto pueda pasar las responsabilidades del iterador a una clase interna, o crear un objeto especial. En cualquier caso, el método __iter __ () generalmente solo tiene una línea y esa línea es a menudo simplemente return self

La otra parte del protocolo es el método next () , y aquí es donde se realiza el trabajo real. Este método tiene que averiguar o crear u obtener lo siguiente, y devolverlo. Es posible que deba hacer un seguimiento de dónde está para que la próxima vez que se llame, realmente devuelva lo siguiente.

Una vez que tienes un objeto que devuelve lo siguiente en una secuencia, puedes colapsar un bucle for que se parece a esto:

myname = "Fredericus"
x = []
for i in [1,2,3,4,5,6,7,8,9,10]:
   x.append(myname[i-1])
   i = i + 1 # get the next i
print x

en esto:

myname = "Fredericus"
x = [myname[i] for i in range(10)]
print x

Observe que no hay ningún lugar en el que tengamos el código que obtenga el siguiente valor de i porque range (10) es un objeto que SIGUE al protocolo del iterador, y la comprensión de la lista es un constructo que UTILIZA el protocolo del iterador.

También puede USAR el protocolo del iterador directamente. Por ejemplo, cuando escribo scripts para procesar archivos CSV, a menudo escribo esto:

mydata = csv.reader(open('stuff.csv')
mydata.next()
for row in mydata:
    # do something with the row.

Estoy usando el iterador directamente llamando a next () para omitir la fila del encabezado y luego usándolo indirectamente a través del operador integrado in en el para declaración.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top