I generatori sono più di semplici iteratori: sono il cuore pulsante di asyncio. Esploreremo tecniche avanzate come yield from, send() e il chaining, fino a svelare come i generatori hanno dato vita alle coroutine moderne. Un talk pratico con esempi concreti per data processing e I/O concorrente.
I generatori Python sono spesso sottovalutati: molti sviluppatori li usano solo per creare iteratori memory-efficient, ignorando il loro potenziale nascosto. In questo talk scopriremo come i generatori siano il fondamento stesso di asyncio e delle coroutine moderne — un viaggio che parte da yield e arriva fino al cuore dell’event loop.
PARTE 1: OLTRE IL SEMPLICE YIELD
Partiremo con un rapido ripasso per allineare tutti, ma andremo subito oltre l’uso basilare:
• Generator expressions vs list comprehensions Quando e perché preferire la lazy evaluation. Vedremo benchmark reali che mostrano come una semplice modifica da […] a (…) possa fare la differenza tra un processo che crasha e uno che gira fluido.
• Il protocollo iterator Cosa succede davvero quando Python incontra yield? Analizzeremo iter, next e StopIteration per capire la magia dietro le quinte.
• Memory footprint in pratica Demo con memory_profiler: elaboreremo un file da 1GB con una list comprehension (spoiler: crash) e poi con un generatore (spoiler: 50MB di RAM).
PARTE 2: TECNICHE AVANZATE
Esploriamo gli aspetti meno conosciuti dei generatori:
• yield from: delegazione elegante Introdotto in Python 3.3 (PEP 380), questo costrutto permette di concatenare generatori creando pipeline di elaborazione dati leggibili e manutenibili. Vedremo come costruire un sistema ETL componibile.
• Generatori bidirezionali con send() I generatori non sono solo “produttori” di valori — possono anche riceverli! Implementeremo insieme un accumulatore running average, una state machine per parsing di protocolli, una coroutine-style consumer.
• throw() e close(): error handling Come propagare eccezioni dentro un generatore e come gestire la cleanup con try/finally. Pattern essenziali per codice production-ready.
PARTE 3: LA CONNESSIONE CON ASYNCIO
Il cuore del talk — la parte che cambia la prospettiva:
• La storia: da yield a async/await Un viaggio attraverso le PEP che hanno trasformato Python:
• Sotto il cofano di asyncio Cosa succede quando scrivi “await”? Spoiler: c’è un generatore. Analizzeremo il codice sorgente di asyncio per vedere come l’event loop usa next() e send() per orchestrare le coroutine.
• Live coding: il nostro mini event loop In 20 righe di codice, costruiremo un event loop funzionante usando solo generatori. Questo esercizio cementa la comprensione del modello mentale dietro asyncio.
• async generators (PEP 525) Il meglio dei due mondi: generatori che possono fare await. Vedremo quando usarli e pattern pratici per streaming asincrono.
PARTE 4: USE CASE REALI
Codice che puoi usare domani:
• Data processing su larga scala Pipeline per elaborare log files, CSV multi-GB, stream JSON. Pattern producer/transformer/consumer con generatori concatenati.
• Web scraping concorrente Combinare aiohttp con async generators per scraping efficiente di migliaia di pagine con backpressure naturale.
• Real-time data pipelines Generatori come “colla” tra Kafka/Redis streams e la logica applicativa. Come mantenere memory footprint costante indipendentemente dal volume.
• Testing e mocking Usare generatori per creare fixture dinamiche e mock di API paginate.
COSA PORTERAI A CASA
• Comprensione profonda dei generatori e del loro ruolo in Python moderno • Il “perché” dietro async/await — non solo il “come” • Pattern riutilizzabili per data processing e concorrenza • La capacità di debuggare asyncio sapendo cosa succede sotto
PER CHI È QUESTO TALK
Ideale per sviluppatori Python intermediate che:
NON è necessario essere esperti di asyncio — anzi, il talk è pensato proprio per demistificarlo.