Skip to content

Latest commit

 

History

History
353 lines (263 loc) · 9.87 KB

File metadata and controls

353 lines (263 loc) · 9.87 KB
title Da Python Fundamentals a Generative Programming
description Il percorso evolutivo: dai fondamenti di Python alla programmazione generativa con AI
icon
tag Percorso
date 2026-01-05

import InfoBox from '../../components/InfoBox.astro'; import Quote from '../../components/Quote.astro'; import ToolCard from '../../components/ToolCard.astro'; import TimelineItem from '../../components/TimelineItem.astro'; import VersionBadge from '../../components/VersionBadge.astro';


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:

  • Le fondamenta di Python (iteratori, funzioni built-in)
  • I pattern idiomatici che rendono Python unico
  • La storia di come Python è diventato il linguaggio dell'AI
  • Le tecniche di programmazione generativa per game development
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
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

Categoria Funzioni Uso
I/O print(), input() Stampa output, legge input utente
Conversione int(), float(), str(), list(), dict() Conversione tra tipi
Matematica len(), sum(), min(), max(), abs(), round() Operazioni numeriche
Iterazione range(), enumerate(), zip(), sorted(), reversed() Lavorare con sequenze
Funzionale map(), filter() Programmare funzionalmente
Introspezione type(), 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)
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

L'AI/ML esisteva già in **LISP** e **Prolog**. Python cresceva come linguaggio "glue" - ottimo per prototipazione e collegare librerie C/C++/Fortran. **NumPy** (2006), **SciPy** (2001), **Matplotlib** (2003) - portano in Python la potenza di MATLAB ma con sintassi più accessibile. **scikit-learn** (2007) - Game changer. Interfaccia unificata per tutti gli algoritmi ML. **Theano** (2007), **TensorFlow** (2015, Google), **PyTorch** (2016, Facebook) - tutti Python-first. "Attention is All You Need" (2017), GPT, BERT, **Hugging Face** - tutto Python.

Perché Python Vinse

Velocissimo ma boilerplate infernale, debugging complicato. **Python:** prototipa in ore, non settimane. Ottimo per statistica ma design inconsistente. **Python:** più versatile. Proprietario, costoso. **Python + NumPy:** MATLAB gratis con più features.

Il Paradosso Interessante

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
    # ...
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

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.