Скачать книгу

que puedar iterarse en él, por ejemplo, en un bucle for, para obtener sus elementos uno a uno. El protocolo se basa en un objeto denominado iterador, el cual dispone de los siguientes métodos:

      • iterator._ _iter_ _(): es un método del objeto que devuelve una referencia al mismo objeto;

      • iterator._ _next_ _(): es un método que devuelve el elemento siguiente del contenedor, o bien detecta una excepción de tipo StopIteration si los elementos del contenedor han sido todos devueltos.

      Un objeto contenedor obj se considera iterable si es posible acceder a sus elementos mediante indexación, o bien si cuenta con un método obj._ _iter_ _() que devuelve un iterador.

      Según estas definiciones, un iterador es un objeto iterable, mientras que un objeto iterable no se considera que sea un iterador. Por ejemplo, un conjunto no es un iterador porque no tiene el método set._ _next_ _():

image

      Veamos si es un objeto iterable. En primer lugar, comprobamos que tenga un método set._ _iter_ _():

image

      A continuación, debemos comprobar que este método devuelva un iterador. Si así fuera, el conjunto sería un objeto iterable. Vamos allá:

image

      Ahora falta una condición para poder afirmar que obj es un interador. Su método obj._ _next_ _() debe devolver a cada llamada el elemento siguiente del contenedor y generar una excepción del tipo StopIteration cuando los elementos han terminado:

image

      En definitiva, las instancias del tipo set son objetos iterables porque tienen un método set._ _iter_ _() que devuelve un iterador, pero no son iteradores porque no tienen el método set._ _next_ _().

      Las funciones integradas iter() y next() también permiten iterar manualmente sobre un objeto iterable:

image

      Una carácterística importante de los iteradores es que quedan vinculados al objeto iterable:

image

      Profundizaremos en este argumento en el Capítulo 6.

      Las clases integradas range y enumerate

      En el Capítulo 2 trataremos las funciones integradas vinculadas a los objetos iterables; de momento nos limitamos a hablar únicamente de las clases range y enumerate. La clase range tiene un argumento stop obligatorio y dos argumentos start y step opcionales:

image

      Devuelve un objeto iterable que contiene una secuencia de números progresivos. Cuando se utiliza con el argumento simple stop, el objeto contiene los números del 0 al stop exclusive:

image image

      Los argumentos opcionales start y step permiten indicar el número de inicio y el intervalo entre un número y el siguiente:

image

      La clase enumerate toma como argumento un objeto iterable y devuelve un iterador que itera sobre tuplas. Cada tupla está formada por un índice progresivo y por un elemento del objeto iterable. Cuando el objeto iterable es una secuencia seq, el índice progresivo corresponde al índice del elemento en la secuencia, por lo que las tuplas serán (idx, seq[idx]):

image

      Acabamos esta parte demostrando una importante diferencia entre iteradores y objetos iterables que no son iteradores. Mientras que para un objeto iterable que no es un iterador es posible utilizar diferentes iteradores sobre él de manera independiente, esto no es posible para un objeto iterador, puesto que el método iteratore._ _iter_ _() devuelve una referencia a sí mismo:

image

      El contexto de iteración

      La instrucción for permite iterar de forma automática sobre los objetos iterables:

image

      De hecho, utiliza el protocolo de iteración para completar automáticamente el proceso que hemos ejecutado manualmente en la sección anterior:

      1. obtiene el iterador: iterador = iter(('a', 'b', 'c'));

      2. solicita el elemento siguiente llamando al método iterador._ _next_ _();

      3. si iterador._ _next_ _() genera una excepción StopIteration, entonces captura la excepción y termina la iteración; si no, pasa al punto 4;

      4. asigna a la etiqueta i el elemento siguiente: i = iterador._ _next_ _();

      5. ejecuta el bloque de instrucciones, que en este caso son la llamada simple a print(i);

      6. regresa al punto 2.

      También los diccionarios y los archivos son objetos iterables. Cuando se itera sobre un diccionario, se itera sobre sus claves: :

image

      mientras que cuando se itera sobre un archivo, se itera sobre sus líneas:

image

      Una importante carácterística de los objetos iterables es que pueden ser desempaquetados:

image

      En esta sección haremos un ejercicio que nos servirá de resumen, y nos permitirá tanto repasar todo lo que hemos visto hasta ahora como introducir nuevos conceptos. Con este objetivo, vamos a analizar un script que lee archivos con extensión .data, realiza algunos cálculos y, por último, guarda los resultados en otro archivo. El script en cuestión es el archivo dataout.py:

image image

      NOTA

      El código fuente de todos los ejercicios finales y de los ejemplos más significativos del libro está disponible en la URL http://code.google.com/p/the-pythonic-way/.

      Es probable que gran parte de este código nos resulte confuso, pero no nos preocupemos, puesto que lo anlizaremos línea a línea en las secciones siguientes. De momento, volvamos a leerlo y esforcémonos al máximo por entender su significado nosotros solos.

      Ejecución del script

      El script lee del directorio actual los archivos con extensión .data y para cada uno de ellos crea un archivo de salida con el mismo nombre, pero con extensión .dataout. Por ejemplo, encuentra un archivo

Скачать книгу