ARTICOLO 📖 7 min lettura

Da Python Fundamentals a Generative Programming

Il percorso evolutivo: dai fondamenti di Python alla programmazione generativa con AI

Da Python Fundamentals a Generative Programming Percorso Completo

Introduzione

La Genesi di Questo Documento

Questo documento nasce da una semplice domanda: “Quali sono tutti gli iteratori di Python?”

Una curiosità genuina che si è trasformata in un’esplorazione più ampia, attraversando:

💡 L'Approccio Software Engineer 3.0

Invece di studiare Python in modo lineare (capitolo 1, capitolo 2…), abbiamo seguito il flusso della curiosità. Questo crea connessioni più profonde e durature. Quando capisci perché Python è diventato il linguaggio dell’AI, comprendi meglio come usarlo efficacemente.


Iteratori: Il Cuore di Python

Gli iteratori sono oggetti che implementano il protocollo di iterazione, permettendo di attraversare sequenze di elementi uno alla volta. Sono il fondamento della filosofia “lazy evaluation” di Python.

Iteratori Built-in

# Sequenze native: liste, tuple, stringhe, range
for item in [1, 2, 3]:
    print(item)

for char in "ciao":
    print(char)

# Dizionari
d = {'a': 1, 'b': 2}
for key, value in d.items():
    print(key, value)

# File - memory efficient
with open('file.txt') as f:
    for line in f:
        print(line.strip())

Funzioni che Restituiscono Iteratori

# map, filter, zip - Lazy evaluation
nums = [1, 2, 3]
squared = map(lambda x: x**2, nums)
print(list(squared))  # [1, 4, 9]

# enumerate - Aggiunge indice
for i, value in enumerate(['a', 'b', 'c'], start=1):
    print(f"{i}: {value}")

Modulo itertools

import itertools

# count - contatore infinito
for i in itertools.count(10, 2):
    if i > 20: break
    print(i)  # 10, 12, 14, 16, 18, 20

# chain - concatena iterabili
for item in itertools.chain([1, 2], [3, 4]):
    print(item)

# combinations
print(list(itertools.combinations([1, 2, 3], 2)))
# [(1, 2), (1, 3), (2, 3)]

Creare Iteratori Personalizzati

# Con generatori (molto più semplice)
def countdown(start):
    while start > 0:
        yield start
        start -= 1

for num in countdown(5):
    print(num)  # 5, 4, 3, 2, 1

Il Potere della Lazy Evaluation

Gli iteratori sono lazy - non caricano tutto in memoria ma generano valori quando richiesti. Questo permette di lavorare con sequenze infinite o dataset enormi senza esaurire la RAM.


Le 20 Funzioni Più Comuni

CategoriaFunzioniUso
I/Oprint(), input()Stampa output, legge input utente
Conversioneint(), float(), str(), list(), dict()Conversione tra tipi
Matematicalen(), sum(), min(), max(), abs(), round()Operazioni numeriche
Iterazionerange(), enumerate(), zip(), sorted(), reversed()Lavorare con sequenze
Funzionalemap(), filter()Programmare funzionalmente
Introspezionetype(), isinstance(), dir(), help()Capire oggetti e tipi

Design Patterns Python

1. List Comprehension

# Base
squares = [x**2 for x in range(10)]

# Con condizione
evens = [x for x in range(20) if x % 2 == 0]

# Nested (appiattire liste)
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [num for row in matrix for num in row]
# [1, 2, 3, 4, 5, 6]

2. Unpacking

# Base
a, b, c = [1, 2, 3]

# Con *rest
first, *rest = [1, 2, 3, 4, 5]
# first = 1, rest = [2, 3, 4, 5]

# Swap elegante
a, b = b, a

# Merge dizionari (Python 3.9+)
merged = {**d1, **d2}

3. Context Manager (with)

with open('file.txt', 'r') as f:
    content = f.read()
# File chiuso automaticamente

# Custom context manager
from contextlib import contextmanager

@contextmanager
def timer():
    import time
    start = time.time()
    yield
    print(f"Elapsed: {time.time() - start}s")

with timer():
    sum(range(1000000))

4. Walrus Operator := (Python 3.8+)

# Assignment expression
if (data := get_data()):
    process(data)

# In while loop
while (line := file.readline()):
    process(line)

ℹ️ Pattern vs Paradigma

Questi pattern non sono solo “sintassi carina”. Sono il modo in cui Python esprime concetti complessi in modo leggibile. List comprehension, per esempio, è più veloce dei loop tradizionali E più facile da leggere.


Come Python è Diventato il Linguaggio dell’AI

La Timeline

Anni '50-'90

Le Origini

L’AI/ML esisteva già in LISP e Prolog. Python cresceva come linguaggio “glue” - ottimo per prototipazione e collegare librerie C/C++/Fortran.

2000-2006

Le Fondamenta Scientifiche

NumPy (2006), SciPy (2001), Matplotlib (2003) - portano in Python la potenza di MATLAB ma con sintassi più accessibile.

2007-2010

L'Ecosistema ML

scikit-learn (2007) - Game changer. Interfaccia unificata per tutti gli algoritmi ML.

2010-2015

Deep Learning Esplode

Theano (2007), TensorFlow (2015, Google), PyTorch (2016, Facebook) - tutti Python-first.

2017-oggi

Era Transformer e LLM

“Attention is All You Need” (2017), GPT, BERT, Hugging Face - tutto Python.

Perché Python Vinse

Contro C++

Velocissimo ma boilerplate infernale, debugging complicato. Python: prototipa in ore, non settimane.

Contro R

Ottimo per statistica ma design inconsistente. Python: più versatile.

Contro MATLAB

Proprietario, costoso. Python + NumPy: MATLAB gratis con più features.

Il Paradosso Interessante

⚠️ Python è 'Lento'. Ma Non Importa.

Python è interpretato, dynamically typed, single-threaded (GIL). Ma per AI non importa perché:

  • Il codice Python è solo “orchestrazione”
  • Il lavoro pesante (matrici, GPU) è in C/C++/CUDA
  • Hai bisogno di velocità di sviluppo, non di runtime
# Questo loop Python è lento
for i in range(1000000):
    result += i * 2

# Ma questo è velocissimo (NumPy in C)
result = np.sum(np.arange(1000000) * 2)

Programmazione Generativa per Game Development

1. Dungeon/Cave Generator (Cellular Automata)

import numpy as np

def generate_cave(width, height, fill_prob=0.45, iterations=4):
    """Genera una caverna usando cellular automata"""
    grid = np.random.choice([0, 1], size=(height, width),
                           p=[1-fill_prob, fill_prob])

    for _ in range(iterations):
        new_grid = grid.copy()
        for y in range(1, height-1):
            for x in range(1, width-1):
                neighbors = np.sum(grid[y-1:y+2, x-1:x+2]) - grid[y, x]
                if neighbors > 4:
                    new_grid[y, x] = 1
                elif neighbors < 4:
                    new_grid[y, x] = 0
        grid = new_grid

    return grid  # 0 = vuoto, 1 = muro

2. Generatore di Sistemi Stellari (Space Game)

import random

class StarSystem:
    def __init__(self, seed=None):
        if seed:
            random.seed(seed)
        self.star = self.generate_star()
        self.planets = self.generate_planets()

    def generate_star(self):
        star_types = [
            ('G', 7.6, (255, 244, 234), 5200),  # nostro sole
            ('K', 12.1, (255, 210, 161), 3700),
            ('M', 76.45, (255, 204, 111), 2400)
        ]
        # ... logica selezione tipo stella

    def generate_planets(self):
        num_planets = random.randint(0, 10)
        # ... generazione pianeti con risorse, lune, tipo

3. Nome Generator (Markov Chains)

def markov_name_generator(sample_names, order=2, count=10):
    """Genera nomi usando Markov chains"""
    chain = {}
    for name in sample_names:
        name = '^' * order + name.lower() + '$'
        for i in range(len(name) - order):
            key = name[i:i+order]
            next_char = name[i+order]
            if key not in chain:
                chain[key] = []
            chain[key].append(next_char)

    # Genera nomi basati sulla chain
    # ...

Per un Space Game

Combinerei:

  1. Perlin noise per galassie/nebulose
  2. StarSystem generator per sistemi stellari
  3. WFC per stazioni spaziali/interni
  4. Markov per nomi

Conclusioni

I Takeaway Chiave

💡 5 Punti Essenziali

  1. Python è un linguaggio di orchestrazione - Il lavoro pesante è in C/CUDA sotto
  2. I pattern sono essenziali - List comprehension, unpacking, context manager sono il modo Pythonic
  3. Lazy evaluation = efficienza - Iteratori e generator expression per dataset enormi
  4. Network effect vince - Python vinse non perché “migliore” ma perché al momento giusto
  5. Generativo = creatività procedurale - Cellular automata, noise functions, L-systems

Il prossimo passo? Prendi uno di questi generatori e costruisci qualcosa. Un dungeon roguelike. Un sistema stellare procedurale. Un generatore di mappe. La teoria si solidifica solo attraverso la pratica.