3.1. Cómo Implementar Objetos Iterables e Iteradores
# 3.1 Cómo implementar objetos iterables e iteradores
import requests
from collections.abc import Iterable, Iterator
class ClimaIterator(Iterator):
def __init__(self, ciudades):
self.ciudades = ciudades
self.indice = 0
def __next__(self):
if self.indice == len(self.ciudades):
raise StopIteration
ciudad = self.ciudades[self.indice]
self.indice += 1
return self.obtener_clima(ciudad)
def obtener_clima(self, ciudad):
url = 'http://wthrcdn.etouch.cn/weather_mini?city=' + ciudad
r = requests.get(url)
data = r.json()['data']['forecast'][0]
return ciudad, data['high'], data['low']
class ClimaIterable(Iterable):
def __init__(self, ciudades):
self.ciudades = ciudades
def __iter__(self):
return ClimaIterator(self.ciudades)
def mostrar(w):
for x in w:
print(x)
clima = ClimaIterable(['Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen', 'Dongguan'])
mostrar(clima)
3.2. Cómo Usar Funciones Generadoras para Implementar Objetos Iterables
# 3.2 Cómo usar funciones generadoras para implementar objetos iterables
from collections.abc import Iterable
class NumerosPrimos(Iterable):
def __init__(self, a, b):
self.a = a
self.b = b
def __iter__(self):
for k in range(self.a, self.b):
if self.es_primo(k):
yield k
def es_primo(self, k):
return False if k < 2 else all(map(lambda x: k % x, range(2, k)))
# Imprimir números primos del 1 al 30
np = NumerosPrimos(1, 30)
for n in np:
print(n)
3.3. Cómo Realizar Iteración Inversa y Cómo Implementarla
Iteración inversa:
l = [1, 2, 3, 4, 5]
for x in l:
print(x)
for x in reversed(l):
print(x)
Para implementar la iteración inversa, se debe definir el método __reversed__:
# 3.3 Cómo realizar iteración inversa y cómo implementarla
class RangoEnteros:
def __init__(self, a, b, paso):
self.a = a
self.b = b
self.paso = paso
def __iter__(self):
t = self.a
while t <= self.b:
yield t
t += self.paso
def __reversed__(self):
t = self.b
while t >= self.a:
yield t
t -= self.paso
rango = RangoEnteros(1, 10, 2)
for x in rango:
print(x)
print('=' * 30)
for y in reversed(rango):
print(y)
3.4. Cómo Realizar Cortes en Iteradores
Corte de iteradores:
l = list(range(10))
print(l[3])
print(l.__getitem__(3))
print(l[2:6])
print(l.__getitem__(slice(2, 6)))
Imprimir las líneas 2 a 5 de un archivo:
# 3.4 Cómo realizar cortes en iteradores
from itertools import islice
f = open('iter_islice')
# Imprimir las líneas 2 a 5 del archivo
for line in islice(f, 1, 5):
print(line)
Implementar una función similar a islice:
def mi_corte(iterable, inicio, fin, paso=1):
for i, x in enumerate(iterable):
if i >= fin:
break
if i >= inicio:
if (i - inicio) % paso == 0:
yield x
print(list(mi_corte(range(1, 20), 4, 10))) # [5, 6, 7, 8, 9, 10]
print(list(mi_corte(range(1, 20), 4, 10, 2))) # [5, 7, 9]
from itertools import islice
print(list(islice(range(1, 20), 4, 10))) # [5, 6, 7, 8, 9, 10]
print(list(islice(range(1, 20), 4, 10, 2))) # [5, 7, 9]
3.5. Cómo Iterar Múltiples Objetos Iterables en un Solo Bucle for
Calcular la suma de las calificaciones de tres materias usando zip:
from random import randint
chino = [randint(60, 100) for _ in range(10)]
matematicas = [randint(60, 100) for _ in range(10)]
ingles = [randint(60, 100) for _ in range(10)]
t = []
for s1, s2, s3 in zip(chino, matematicas, ingles):
t.append(s1 + s2 + s3)
print(t)
Contar el número total de calificaciones superiores a 90 en tres clases usando chain:
c1 = [randint(60, 100) for _ in range(1, 10)]
c2 = [randint(60, 100) for _ in range(1, 10)]
c3 = [randint(60, 100) for _ in range(1, 10)]
from itertools import chain
total_superior_90 = len([x for x in chain(c1, c2, c3) if x > 90])
print(total_superior_90)