Implementación de Iterables, Iteradores y Operaciones con Iteradores en Python

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)

Etiquetas: Python iterables iterators generators Zip

Publicado el 7-31 02:11