Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Iterables
El protocolo Iterable se usa por tipos donde es posible procesar sus contenidos de uno en
uno, en orden. Un Iterable es un objeto que va a proporcionar un Iterator que puede ser
usado para realizar este proceso.
Hay muchos tipos iterables en Python incluyendo List, Sets, Dictionaries, Tuples, etc. Todos
ellos son contenedores iterables que pueden proporcionar un iterador.
Para ser un tipo iterable solo es necesario implementar el método __iter__() (que es el
único método en el protocolo Iterable ). Este método debe proporcionar una referencia al
objeto Iterator . Esta referencia puede ser al propio tipo de dato o puede ser a cualquier otro
tipo que implemente el protocolo Iterator .
Iteradores
Un iterador es un objeto que devuelve una secuencia de valores. Esta secuencia puede ser
finita en longitud o infinita (aunque mucho iteradores orientados a contenedores proporcionan
un conjunto fijo de valores).
Como ejemplo vamos a crear una clase llamada Pares que devuelva números pares entre 0 y
un determinado límite. Este nuevo tipo va a actuar simultaneamente como Iterable y como
Iterator al implementar ambos protocolos.
1 class Pares(object):
2
3 def __init__(self, limite):
4 self.limite = limite
5 self.valor = 0
6
7 def __iter__(self):
8 return self
9
10 def __next__(self):
11 if self.valor > self.limite:
12 raise StopIteration
13 else:
14 valor_actual = self.valor
self.valor += 2
return valor_actual
15
16
Resultado:
0, 2, 4, 6, 8, 10, Fin
Generadores
Un generador (Generator) es una función especial que se puede usar para generar una
secuencia de valores para iterar sobre ellos a demanda. Para ello se utiliza la palabra clave
yield . Esta palabra clave solo se puede utilizar dentro de una función o de un método.
1 def genera_numeros():
2 yield 1
3 yield 2
4 yield 3
5
6 for numero in genera_numeros():
7 print(numero, end=', ')
8 print('Fin')
Resultado:
1, 2, 3, Fin
La función genera_numeros es una función especial que devuelve un objeto Generator que
es el que genera los valores requeridos para la iteración del for.
Veamos el mismo ejemplo enriquecido para que nos aclare el orden de ejecución de las cosas:
1 def genera_numeros():
2 print('Inicio')
3 yield 1
4 print('Siguiente')
5 yield 2
6 print('Otro mas')
7 yield 3
8 print('Termino')
9
10 for numero in genera_numeros():
11 print(numero)
12 print('Fin')
Resultado:
Inicio
1
Siguiente
2
Otro mas
3
Termino
Fin
Vamos a reescribir el ejemplo del iterable de Pares utilizando una función que actue como
generador. Veremos que queda mucho más sencillo.
1 def pares_hasta(limite):
2 valor = 0
3 while valor <= limite:
4 yield valor
5 valor += 2
6
7 for numero in pares_hasta(10):
8 print(numero, end=', ')
9 print('Fin')
Resultado:
0, 2, 4, 6, 8, 10, Fin
No es necesario un bucle for para trabajar con una función generador. El objeto generador
que devuelve la función soporta la función next . Esta función se invoca pasando como
argumento el objeto generador y devuelve el siguiente valor de la secuencia.
1 def pares_hasta(limite):
2 valor = 0
3 while valor <= limite:
4 yield valor
5 valor += 2
6
7 pares = pares_hasta(4)
8 print(next(pares))
9 print(next(pares))
10 print(next(pares))
Resultado:
0
2
4
Corutinas
Las corutinas (coroutines) son muy similares a los generadores pero con una diferencia: los
generadores producen datos y las corutinas los consumen. Las corutinas son funciones que
mediante la palabra clave yield esperan en ese punto a recibir un dato que les es
suministrado mediante la función send() .
Es necesario iniciar la corutina al principio con un next o con un send(None) . Esto avanza la
corutina hasta el yield donde se queda esperando a recibir datos para procesarlos.
Veamos un ejemplo que examina si los textos enviados a una corutina contienen una
determinada palabra:
1 def buscar(palabra):
2 print('Buscando palabra', palabra)
3 try:
4 while True:
5 linea = (yield)
6 if palabra in linea:
7 print(linea)
8 except GeneratorExit:
9 print('Saliendo de la corutina')
10
11 print('Inicio')
12 # Creamos la corutina
13 g = buscar('Python')
14
15 # Inicializamos la corutina
16 next(g)
17
18 # Enviamos datos a la corutina
19 g.send('C# es muy versatil')
20 g.send('Python es muy sencillo')
21 g.send('C++ es muy potente')
22
23 # Cerramos la corutina
24 g.close()
25 print('Fin')
Resultado:
Inicio
Buscando palabra Python
Python es muy sencillo
Saliendo de la corutina
Fin