- Home
- iThink
- Programmazione per Ragazzi
- Moduli e librerie standard di Python
Moduli e librerie standard di Python
Divento Programmatore — Capitolo 6: Moduli e librerie standard
Hai imparato a scrivere funzioni (Cap. 4) e gestire dati (Cap. 5). Ora impari a organizzare il codice in file riutilizzabili e usare la batteria inclusa di Python: centinaia di moduli pronti all'uso.
Cosa imparerai
| Concetto | Descrizione | | ---------- | ------------- | | Modulo | File .py con funzioni/classi/variabili | | import | Carica modulo nel namespace | | Standard Library | Moduli inclusi in Python (batterie incluse) | | random | Numeri casuali per giochi | | time | Timing, sleep, misurazione prestazioni | | math | Funzioni matematiche avanzate | | pip | Installa pacchetti terze parti (PyPI) |
1. Cos'è un modulo?
Un modulo è semplicemente un file Python (es. utilita.py). Lo importi per usare ciò che contiene.
progetto/
├── main.py # Il tuo script principale
├── utilita.py # Tuo modulo personale
└── gioco/
├── __init__.py # Rende 'gioco' un package
├── nemici.py
└── armi.py
2. Import: le forme principali
# 1. Importa tutto il modulo (namespace: modulo.nome)
import math
print(math.pi)
print(math.sqrt(16))
# 2. Importa nomi specifici (namespace diretto)
from math import pi, sqrt, sin
print(pi)
print(sqrt(16))
# 3. Importa con alias (evita conflitti nomi)
import random as rnd
print(rnd.randint(1, 6))
# 4. Importa tutto (⚠️ SCONSIGLIATO: inquina namespace)
from math import *
print(pi) # Funziona, ma da dove viene pi?
Best practice: Usa forma 1 o 2. Forma 3 per moduli con nomi lunghi (numpy as np, pandas as pd).
3. La Standard Library: i "must" per i giochi
random — Casualità controllata
import random
# Interi
random.randint(1, 6) # 1-6 inclusi (dado)
random.randrange(1, 7) # 1-6 (stop escluso)
random.randrange(0, 101, 2) # Pari 0-100
# Float
random.random() # 0.0 - 1.0
random.uniform(1.5, 5.5) # Float in range
# Scelte da sequenza
random.choice(["rosso", "blu", "verde"]) # Un elemento
random.choices([1,2,3], k=5) # Lista 5 elementi (con ripetizioni)
random.sample(range(1, 50), 6) # 6 unici (senza ripetizioni) - tipo SuperEnalotto
# Mescola IN PLACE
carte = list(range(52))
random.shuffle(carte)
# Seed per riproducibilità (test, debug)
random.seed(42)
print(random.randint(1, 10)) # Sempre stesso "casuale"
Sicurezza:
randomnon è crittografico. Per password e token usa il modulosecrets.
time — Tempo e attese
import time
# Timestamp attuale (secondi da epoch 1970)
now = time.time() # float: 1703000000.123456
# Sleep (pausa esecuzione)
time.sleep(1) # 1 secondo
time.sleep(0.5) # 500 ms
# Misurare durata codice (alta precisione)
start = time.perf_counter()
# ... codice da misurare ...
end = time.perf_counter()
print(f"Durata: {end - start:.4f} secondi")
# Formattazione leggibile
print(time.ctime()) # 'Mon Dec 18 10:30:45 2023'
print(time.strftime("%Y-%m-%d %H:%M:%S")) # '2023-12-18 10:30:45'
math — Matematica avanzata
import math
# Costanti
math.pi # 3.141592653589793
math.e # 2.718281828459045
math.tau # 2*pi = 6.283185307179586
# Potenze e radici
math.sqrt(16) # 4.0
math.pow(2, 10) # 1024.0 (float)
2 ** 10 # 1024 (int, preferibile)
# Trigonometria (argomenti in RADIANTI)
math.sin(math.pi / 2) # 1.0
math.cos(0) # 1.0
math.radians(180) # pi (gradi → radianti)
math.degrees(math.pi) # 180.0 (radianti → gradi)
# Logaritmi
math.log(100, 10) # 2.0 (base 10)
math.log(100) # ln(100) (base e)
math.log10(100) # 2.0
math.log2(8) # 3.0
# Arrotondamenti
math.ceil(3.2) # 4 (su)
math.floor(3.8) # 3 (giù)
math.trunc(3.8) # 3 (taglia decimali)
round(3.5) # 4 (banker's rounding)
# Utilità
math.hypot(3, 4) # 5.0 (ipotenusa: sqrt(x²+y²))
math.dist((0,0), (3,4)) # 5.0 (distanza 2D, Py 3.8+)
math.gcd(48, 18) # 6 (mcd)
math.lcm(4, 6) # 12 (mcm, Py 3.9+)
datetime — Date e orari (oggetti, non stringhe)
from datetime import datetime, timedelta, date
now = datetime.now() # 2023-12-18 10:30:45.123456
today = date.today() # 2023-12-18
# Formattazione
print(now.strftime("%d/%m/%Y %H:%M")) # 18/12/2023 10:30
# Parsing
dt = datetime.strptime("25/12/2023", "%d/%m/%Y")
# Aritmetica date
domani = today + timedelta(days=1)
tra_un_ora = now + timedelta(hours=1)
diff = domani - today # timedelta(days=1)
os, sys, pathlib — Sistema (anticipazione)
import os
import sys
from pathlib import Path
# Path moderni (pathlib, Py 3.4+)
base = Path(__file__).parent
file = base / "dati" / "salvataggio.json"
file.parent.mkdir(parents=True, exist_ok=True) # Crea cartelle
# Variabili ambiente
os.getenv("HOME") # Path home utente
os.environ.get("DEBUG") # Legge env var
# Info sistema
sys.platform # 'linux', 'darwin', 'win32'
sys.version # Versione Python
4. Creare i tuoi moduli
File: matematica_gioco.py
"""Utilità matematiche per giochi 2D."""
import math
from typing import Tuple
# Costanti di modulo (convenzione: MAIUSCOLO)
GRAVITA = 9.81
GRADI_IN_RADIANTI = math.pi / 180
def distanza(p1: Tuple[float, float], p2: Tuple[float, float]) -> float:
"""Distanza euclidea tra due punti (x, y)."""
return math.hypot(p2[0] - p1[0], p2[1] - p1[1])
def angolo_verso(origine: Tuple[float, float],
destinazione: Tuple[float, float]) -> float:
"""Angolo in gradi da origine a destinazione (0=est, 90=nord)."""
dx = destinazione[0] - origine[0]
dy = destinazione[1] - origine[1]
return math.degrees(math.atan2(dy, dx))
def muovi_verso(pos: Tuple[float, float],
angolo_gradi: float,
velocita: float) -> Tuple[float, float]:
"""Nuova posizione muovendosi verso angolo con velocità data."""
rad = angolo_gradi * GRADI_IN_RADIANTI
return (pos[0] + math.cos(rad) * velocita,
pos[1] + math.sin(rad) * velocita)
# Codice eseguibile solo se lancio diretto: python matematica_gioco.py
if __name__ == "__main__":
# Test rapido / demo
p1 = (0, 0)
p2 = (10, 10)
print(f"Distanza: {distanza(p1, p2):.2f}")
print(f"Angolo: {angolo_verso(p1, p2):.1f}°")
print(f"Muovi 5 unità: {muovi_verso(p1, 45, 5)}")
File: main.py (usa il modulo)
import matematica_gioco as mg
player = (100, 100)
target = (200, 150)
ang = mg.angolo_verso(player, target)
dist = mg.distanza(player, target)
new_pos = mg.muovi_verso(player, ang, 10)
print(f"Angolo: {ang:.1f}°, Distanza: {dist:.1f}, Nuova pos: {new_pos}")
5. __name__ == "__main__": pattern fondamentale
# mio_modulo.py
def funzione_utile():
return "Utile!"
def _privata(): # Convenzione: _prefix = interno
return "Non importare"
# Questo blocco gira SOLO se: python mio_modulo.py
# NON gira se: import mio_modulo
if __name__ == "__main__":
print("Test modulo:")
print(funzione_utile())
# Test, demo, CLI entry point qui
Perché serve:
- Permette di usare il file come script E come modulo
- Test automatici (
pytestimporta, non esegue main) - Entry point CLI (
python -m mio_pacchetto)
6. Package: cartelle con __init__.py
gioco/
├── __init__.py # Inizializzazione package
├── core/
│ ├── __init__.py
│ ├── motore.py
│ └── entita.py
├── sistemi/
│ ├── __init__.py
│ ├── combattimento.py
│ └── inventario.py
└── ui/
├── __init__.py
└── hud.py
gioco/__init__.py (esporta API pubblica):
"""Gioco RPG - Package principale."""
from .core.motore import MotoreGioco
from .sistemi.combattimento import Combattimento
from .sistemi.inventario import Inventario
__version__ = "1.0.0"
__all__ = ["MotoreGioco", "Combattimento", "Inventario"]
Uso:
from gioco import MotoreGioco, Inventario
from gioco.sistemi.combattimento import Combattimento
7. Pacchetti esterni: pip e PyPI
Installazione
# Terminale (non dentro Python!)
pip install pygame # Libreria giochi 2D
pip install requests # HTTP client
pip install pillow # Immagini
pip install numpy # Array numerici (base per ML/grafica)
requirements.txt (condividi dipendenze)
pygame>=2.5.0
requests>=2.31.0
pillow>=10.0.0
pip install -r requirements.txt # Installa tutto
pip freeze > requirements.txt # Genera da ambiente attuale
Virtual environments (best practice)
python -m venv venv # Crea ambiente isolato
source venv/bin/activate # Linux/macOS
venv\Scripts\activate # Windows
pip install pygame # Installa solo qui
deactivate # Esci
Per ragazzi: Su Thonny → Tools → Manage packages → installa lì. Thonny gestisce venv automatico.
8. Script completo: Toolkit gioco con moduli
toolkit_gioco/__init__.py
"""Toolkit base per giochi 2D."""
from .vettore import Vettore2D
from .timer import Timer
from .casuale import Casuale
__all__ = ["Vettore2D", "Timer", "Casuale"]
toolkit_gioco/vettore.py
"""Vettore 2D con operazioni comuni."""
from math import hypot, cos, sin, radians, degrees, atan2
from typing import Tuple
class Vettore2D:
def __init__(self, x: float = 0, y: float = 0):
self.x = x
self.y = y
def __add__(self, other: "Vettore2D") -> "Vettore2D":
return Vettore2D(self.x + other.x, self.y + other.y)
def __mul__(self, scalare: float) -> "Vettore2D":
return Vettore2D(self.x * scalare, self.y * scalare)
def lunghezza(self) -> float:
return hypot(self.x, self.y)
def normalizzato(self) -> "Vettore2D":
l = self.lunghezza()
return Vettore2D(self.x / l, self.y / l) if l > 0 else Vettore2D(0, 0)
def angolo(self) -> float:
return degrees(atan2(self.y, self.x))
@classmethod
def da_angolo(cls, angolo_gradi: float, lunghezza: float = 1) -> "Vettore2D":
rad = radians(angolo_gradi)
return cls(cos(rad) * lunghezza, sin(rad) * lunghezza)
def __repr__(self):
return f"Vettore2D({self.x:.2f}, {self.y:.2f})"
toolkit_gioco/timer.py
"""Timer per cooldown, durate, FPS."""
import time
class Timer:
def __init__(self, durata: float):
self.durata = durata
self.inizio = 0
self.attivo = False
def avvia(self):
self.inizio = time.perf_counter()
self.attivo = True
def pronto(self) -> bool:
if not self.attivo:
return False
if time.perf_counter() - self.inizio >= self.durata:
self.attivo = False
return True
return False
def reset(self):
self.attivo = False
@property
def rimanente(self) -> float:
if not self.attivo:
return 0
return max(0, self.durata - (time.perf_counter() - self.inizio))
toolkit_gioco/casuale.py
"""Wrapper random con seed e utility gioco."""
import random
from typing import List, TypeVar, Sequence
T = TypeVar('T')
class Casuale:
def __init__(self, seed: int = None):
self.rng = random.Random(seed)
def intero(self, a: int, b: int) -> int:
return self.rng.randint(a, b)
def float(self, a: float = 0, b: float = 1) -> float:
return self.rng.uniform(a, b)
def scelta(self, seq: Sequence[T]) -> T:
return self.rng.choice(seq)
def scelte(self, seq: Sequence[T], k: int) -> List[T]:
return self.rng.choices(seq, k=k)
def campione(self, seq: Sequence[T], k: int) -> List[T]:
return self.rng.sample(seq, k)
def mescola(self, lst: List[T]) -> None:
self.rng.shuffle(lst)
def probabilita(self, p: float) -> bool:
"""True con probabilità p (0.0-1.0)."""
return self.rng.random() < p
demo_toolkit.py
"""Demo toolkit gioco."""
from toolkit_gioco import Vettore2D, Timer, Casuale
import time
rng = Casuale(42) # Seed fisso per demo riproducibile
# Vettore
player = Vettore2D(100, 100)
direzione = Vettore2D.da_angolo(45, 10)
player = player + direzione
print(f"Player si muove a: {player}")
# Timer cooldown
cooldown = Timer(1.0) # 1 secondo
cooldown.avvia()
print("Attacco! Cooldown avviato...")
while not cooldown.pronto():
time.sleep(0.2)
print(f" Rimanente: {cooldown.rimanente:.1f}s")
print("Pronto per nuovo attacco!")
# Casuale
print(f"Dado: {rng.intero(1, 6)}")
print(f"Critico (20%): {rng.probabilita(0.2)}")
loot = ["spada", "scudo", "pozione", "oro"]
print(f"Loot: {rng.scelta(loot)}")
9. Tabella riassuntiva: import cheat sheet
| Sintassi | Quando usare | Esempio | | ---------- | -------------- | --------- | | import modulo | Default, namespace pulito | import math | | from modulo import nome | Usi 1-2 cose spesso | from math import pi, sin | | import modulo as alias | Nome lungo / conflitto | import random as rnd | | from . import modulo | Import relativo (stesso package) | from . import vettore | | from .. import modulo | Import relativo (package padre) | from ..core import motore |
10. Esercizi pratici
- Modulo
dadi.py: Funzionid6(),d20(),roll(ndm)es.roll("3d6")→ somma 3 dadi 6 facce - Modulo
colori.py: CostantiROSSO = (255,0,0), funzionimescola_colori(c1, c2),scala_grigi(colore) - Package
utilita: Crea cartella constringhe.py,liste.py,file.py,__init__.pyche esporta tutto - Virtual env: Crea
venv, installapygame, scrivi script che importa e stampapygame.version.ver - Refactoring: Sposta funzioni matematiche Cap. 4 in
matematica.py, importale incalcolatrice.py
11. Checklist fine capitolo
- [ ] Usi
import,from ... import,import ... as - [ ] Conosci
random:randint,choice,shuffle,seed - [ ] Usi
time:sleep,perf_counter,strftime - [ ] Usi
math:sqrt,sin/cos,hypot,radians/degrees - [ ] Crea moduli
.pypropri e li importi - [ ] Capisci
if __name__ == "__main__": - [ ] Sai creare package con
__init__.py - [ ] Usi
pip installerequirements.txt
Prossimo capitolo
Capitolo 7: Pygame e i primi giochi — Finestra, loop eventi, disegna forme, input tastiera/mouse. La libreria standard per giochi 2D in Python.
Serie "Divento Programmatore: Python e i Giochi" (Cervello Elettronico Vol.2). Codice completo, tabelle, esercizi. Target 10-14 anni + guide adulti.
Per approfondire
- Il gioco dell'impiccato in Python
- Disegnare con Python: arte con il modulo turtle
- Liste e dizionari in Python con esempi pratici
- Corsi e percorsi di programmazione