kb.erickguedes.com
Python: De Noob a Hero

Generators, Iterators e Async

Aula 8 de 10

Iterators

class Contador:
    def __init__(self, max):
        self.max = max
        self.atual = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.atual >= self.max:
            raise StopIteration
        self.atual += 1
        return self.atual

for n in Contador(5):
    print(n)  # 1, 2, 3, 4, 5

Generators

# Generator function
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci()
for _ in range(10):
    print(next(fib))  # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

# Generator expression
quadrados = (x**2 for x in range(10))
print(list(quadrados))

# Pipeline com generators
def ler_linhas(arquivo):
    for linha in open(arquivo):
        yield linha.strip()

def filtrar(linhas, padrao):
    for linha in linhas:
        if padrao in linha:
            yield linha

def contar(palavras):
    from collections import Counter
    return Counter(palavras)

# pipeline = contar(filtrar(ler_linhas("log.txt"), "ERROR"))

Async/Await

import asyncio

async def tarefa(nome, tempo):
    print(f"{nome}: iniciando")
    await asyncio.sleep(tempo)
    print(f"{nome}: concluído após {tempo}s")
    return f"Resultado de {nome}"

async def main():
    # Sequencial
    await tarefa("A", 2)
    await tarefa("B", 1)

    # Paralelo
    resultados = await asyncio.gather(
        tarefa("C", 3),
        tarefa("D", 1),
        tarefa("E", 2),
    )
    print(resultados)

    # Timeout
    try:
        await asyncio.wait_for(tarefa("F", 10), timeout=2)
    except asyncio.TimeoutError:
        print("Timeout!")

asyncio.run(main())

HTTP Async com aiohttp

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as resp:
        return await resp.text()

async def main():
    async with aiohttp.ClientSession() as session:
        tasks = [
            fetch(session, f"https://api.github.com/users/{user}")
            for user in ["python", "microsoft", "google"]
        ]
        resultados = await asyncio.gather(*tasks)
        for r in resultados:
            print(len(r))

asyncio.run(main())

Generators criam sequências sem alocar memória para todos os elementos. Async é ideal para I/O-bound (HTTP, bancos, arquivos). Para CPU-bound, use multiprocessing.