Vai al contenuto

2025 – prof. Roberto Fuligni

Introduzione a Python per l'insegnamento

Questo capitolo fornisce le basi della programmazione Python orientate all'insegnamento delle discipline STEM. Acquisirai le competenze fondamentali che ti permetteranno di utilizzare Python come strumento didattico nelle tue lezioni.

Sintassi di base e prime operazioni

Python è un linguaggio di programmazione noto per la sua sintassi chiara e leggibile, che lo rende particolarmente adatto all'insegnamento.

Python segue una filosofia di design che privilegia la leggibilità e la semplicità. Questo approccio è riassunto nel documento "The Zen of Python" che puoi visualizzare digitando import this in un interprete Python.

Commenti e documentazione

I commenti sono parti di codice non eseguite che servono a spiegare cosa fa il programma:

# Questo è un commento su una singola riga

"""
Questo è un commento 
su più righe (docstring)
utile per documentare funzioni e moduli
"""

Indentazione

In Python, l'indentazione non è solo una convenzione stilistica ma è parte della sintassi:

if temperatura > 30:
    print("Fa caldo!")  # Notare l'indentazione
    consiglio = "Bevi molta acqua"
else:
    print("La temperatura è accettabile")
    consiglio = "Goditi la giornata"

Operazioni aritmetiche

Python supporta tutte le operazioni matematiche di base:

# Operazioni fondamentali
somma = 5 + 3       # 8
differenza = 5 - 3  # 2
prodotto = 5 * 3    # 15
quoziente = 5 / 3   # 1.6666... (divisione)
quoziente_intero = 5 // 3  # 1 (divisione intera)
resto = 5 % 3       # 2 (resto della divisione)
potenza = 5 ** 3    # 125 (5 elevato a 3)

Operatori di confronto e logici

# Operatori di confronto
uguale = 5 == 5             # True
diverso = 5 != 3            # True
maggiore = 5 > 3            # True
maggiore_uguale = 5 >= 5    # True
minore = 5 < 10             # True
minore_uguale = 5 <= 5      # True

# Operatori logici
and_logico = True and False  # False
or_logico = True or False    # True
not_logico = not True        # False

Input e output

L'interazione con l'utente avviene tramite le funzioni input() e print():

# Output
print("Benvenuto al calcolatore di formule!")
print("Il risultato è:", 2 + 3)  # Il risultato è: 5

# Input
nome = input("Come ti chiami? ")
print("Ciao", nome)

# Input numerico (converti la stringa in numero)
eta = int(input("Quanti anni hai? "))
print("Tra 10 anni avrai", eta + 10, "anni")

Formattazione del testo

Python offre diversi modi per formattare le stringhe:

nome = "Maria"
punteggio = 9.5

# Metodo f-string (più moderno, Python 3.6+)
messaggio = f"La studentessa {nome} ha ottenuto {punteggio} punti"

# Metodo format()
messaggio = "La studentessa {} ha ottenuto {} punti".format(nome, punteggio)

# Formattazione numerica
pi_greco = 3.14159
messaggio = f"Pi greco arrotondato a due decimali: {pi_greco:.2f}"  # 3.14

Variabili, tipi di dati e strutture dati fondamentali

Variabili

In Python, le variabili sono etichette che puntano a oggetti in memoria:

x = 10  # x è un'etichetta che punta all'intero 10
y = x   # ora anche y punta allo stesso oggetto
x = 20  # x ora punta a un nuovo oggetto (20), ma y punta ancora a 10

Tipi di dati principali

Python ha diversi tipi di dati integrati:

# Numeri
intero = 42
decimale = 3.14159
complesso = 2 + 3j

# Booleani
vero = True
falso = False

# Stringhe
nome = "Python"
frase = 'Didattica computazionale'
testo_lungo = """Questo è un testo
che si estende su
più righe"""

# None (valore nullo)
vuoto = None

Per verificare il tipo di una variabile, usiamo la funzione type():

x = 10
print(type(x))  # <class 'int'>

Strutture dati fondamentali

Liste

Le liste sono strutture dati fondamentali in Python, sequenze mutabili (modificabili) che possono contenere elementi di diversi tipi. Sono definite da parentesi quadre [] e gli elementi sono separati da virgole ,.

# Creazione di liste
numeri = [1, 2, 3, 4, 5]
dati_misti = [1, "due", 3.0, [4, 5]]

# Accesso agli elementi (l'indice parte da 0)
primo = numeri[0]       # 1
ultimo = numeri[-1]     # 5

# Slicing (sottoliste)
primi_tre = numeri[0:3]  # [1, 2, 3]
da_secondo = numeri[1:]  # [2, 3, 4, 5]
fino_terzo = numeri[:3]  # [1, 2, 3]

# Modifica
numeri[0] = 10          # ora numeri = [10, 2, 3, 4, 5]

# Metodi utili
numeri.append(6)        # Aggiunge 6 alla fine: [10, 2, 3, 4, 5, 6]
numeri.insert(1, 15)    # Inserisce 15 in posizione 1: [10, 15, 2, 3, 4, 5, 6]
numeri.remove(3)        # Rimuove il valore 3: [10, 15, 2, 4, 5, 6]
elemento = numeri.pop() # Rimuove e restituisce l'ultimo elemento (6)
lunghezza = len(numeri) # 5

# Iterazione
for numero in numeri:
    print(numero)

Tuple

Le tuple sono simili alle liste ma sono immutabili (non modificabili):

# Creazione di tuple
coordinate = (10, 20)
punto_3d = (10, 20, 30)

# Accesso (come per le liste)
x = coordinate[0]  # 10

# Le tuple non possono essere modificate dopo la creazione
# coordinate[0] = 15  # Questo genererebbe un errore

# Tupla con un elemento (richiede una virgola)
singolo = (42,)

Dizionari

I dizionari sono collezioni di coppie chiave-valore, dove ogni chiave è unica e identifica un valore associato. In Python, i dizionari sono implementati come oggetti di tipo dict e sono definiti utilizzando parentesi graffe {}.

# Creazione di dizionari
studente = {
    "nome": "Laura",
    "età": 16,
    "materie": ["Matematica", "Fisica", "Informatica"]
}

# Accesso ai valori
nome = studente["nome"]           # Laura
materie = studente["materie"]     # ["Matematica", "Fisica", "Informatica"]

# Modifica dei valori
studente["età"] = 17              # Aggiorna l'età
studente["classe"] = "4A"         # Aggiunge una nuova coppia chiave-valore

# Verifica dell'esistenza di una chiave
if "voto" in studente:
    print(studente["voto"])
else:
    print("Voto non presente")

# Metodi utili
chiavi = studente.keys()          # Oggetto view con le chiavi
valori = studente.values()        # Oggetto view con i valori
coppie = studente.items()         # Oggetto view con tutte le coppie (chiave, valore)

# Iterazione
for chiave in studente:
    print(chiave, ":", studente[chiave])

for chiave, valore in studente.items():
    print(chiave, ":", valore)

Set

I set sono collezioni non ordinate di elementi unici e mutabili che possono essere utilizzati per eseguire operazioni insiemistiche.

# Creazione di set
numeri_unici = {1, 2, 3, 4, 5}
altro_set = set([1, 2, 2, 3, 4])  # Crea {1, 2, 3, 4} (i duplicati vengono eliminati)

# Operazioni insiemistiche
unione = numeri_unici | {4, 5, 6}         # {1, 2, 3, 4, 5, 6}
intersezione = numeri_unici & {4, 5, 6}   # {4, 5}
differenza = numeri_unici - {4, 5}        # {1, 2, 3}

# Aggiunta e rimozione di elementi
numeri_unici.add(6)               # Aggiunge 6
numeri_unici.remove(1)            # Rimuove 1 (genera errore se non presente)
numeri_unici.discard(10)          # Prova a rimuovere 10 (non genera errore se non presente)

Conversione tra tipi di dati

Python permette di convertire facilmente tra vari tipi di dati:

# Conversioni di base
stringa_numero = "42"
numero = int(stringa_numero)   # 42 (intero)
numero_float = float(stringa_numero)  # 42.0 (float)

numero_a_stringa = str(42)     # "42" (stringa)

lista_da_stringa = list("ciao")  # ['c', 'i', 'a', 'o']
tupla_da_lista = tuple([1, 2, 3])  # (1, 2, 3)

Funzioni e modularità

Definizione e chiamata di funzioni

Le funzioni permettono di organizzare il codice in blocchi riutilizzabili. In Python, le funzioni sono definite utilizzando la parola chiave def, possono accettare parametri e restituire valori.

# Definizione di una funzione semplice
def saluta():
    print("Ciao, benvenuto!")

# Chiamata della funzione
saluta()  # Output: Ciao, benvenuto!

# Funzione con parametri
def saluta_persona(nome):
    print(f"Ciao {nome}, benvenuto!")

saluta_persona("Marco")  # Output: Ciao Marco, benvenuto!

# Funzione con valore di ritorno
def area_rettangolo(base, altezza):
    return base * altezza

superficie = area_rettangolo(5, 10)  # superficie = 50

Parametri delle funzioni

Python offre diverse opzioni per i parametri:

# Parametri posizionali
def descrivi_persona(nome, età, città):
    return f"{nome} ha {età} anni e vive a {città}"

# Parametri con valori predefiniti (default)
def saluto(nome, messaggio="Ciao"):
    return f"{messaggio}, {nome}!"

print(saluto("Maria"))              # "Ciao, Maria!"
print(saluto("Giovanni", "Buongiorno"))  # "Buongiorno, Giovanni!"

# Numero variabile di parametri
def somma(*numeri):
    risultato = 0
    for n in numeri:
        risultato += n
    return risultato

print(somma(1, 2))        # 3
print(somma(1, 2, 3, 4))  # 10

# Parametri nominali variabili
def descrivi_studente(**dati):
    descrizione = "Studente:\n"
    for chiave, valore in dati.items():
        descrizione += f"- {chiave}: {valore}\n"
    return descrizione

print(descrivi_studente(nome="Alice", età=16, classe="4B"))

Scope delle variabili

In Python, lo scope (ambito di validità) delle variabili determina dove queste sono accessibili:

x = 10  # Variabile globale

def funzione():
    y = 5  # Variabile locale
    print(x)  # Può accedere alla variabile globale x
    print(y)  # Può accedere alla variabile locale y

funzione()
print(x)  # Funziona: x è globale
# print(y)  # Errore: y è locale alla funzione

def modifica_globale():
    global x  # Dichiara che vogliamo usare la x globale
    x = 20    # Modifica la x globale

modifica_globale()
print(x)  # Output: 20

Importazione e utilizzo di moduli

I moduli sono file Python che contengono definizioni e istruzioni. Permettono di organizzare il codice in parti logiche riutilizzabili:

# Importare un intero modulo
import math
print(math.pi)          # 3.141592653589793
print(math.sqrt(16))    # 4.0

# Importare specifiche funzioni/oggetti
from math import pi, sqrt
print(pi)               # 3.141592653589793
print(sqrt(16))         # 4.0

# Importare con alias
import math as m
print(m.pi)             # 3.141592653589793

# Importare tutte le definizioni (da usare con cautela)
from math import *
print(sin(pi/2))        # 1.0

Creare moduli personalizzati

Puoi creare i tuoi moduli salvando il codice in un file .py:

# File: geometria.py
def area_rettangolo(base, altezza):
    return base * altezza

def area_cerchio(raggio):
    import math
    return math.pi * raggio**2

Poi puoi usarlo in un altro file:

# Nel tuo script principale
import geometria

area1 = geometria.area_rettangolo(5, 10)  # 50
area2 = geometria.area_cerchio(3)         # circa 28.27

Concetti di programmazione applicati alla didattica

Algoritmi e pensiero algoritmico

Un algoritmo è una sequenza finita di istruzioni ben definite per risolvere un problema:

# Algoritmo per calcolare la media di una serie di voti
def calcola_media(voti):
    if len(voti) == 0:
        return 0

    somma = 0
    for voto in voti:
        somma += voto

    return somma / len(voti)

# Esempio di utilizzo in contesto didattico
voti_classe = [7, 8, 6, 9, 7, 8]
media = calcola_media(voti_classe)
print(f"La media della classe è {media}")  # La media della classe è 7.5

Strutture di controllo

Le strutture di controllo determinano il flusso di esecuzione di un programma. Sono utilizzate per ripetere un blocco di codice, eseguire una parte di codice solo se una determinata condizione è vera, saltare tra diverse alternative.

Strutture condizionali (if-elif-else)

Strutture condizionali (if-elif-else)

Le strutture condizionali permettono di eseguire un blocco di codice solo se una determinata condizione è vera. Ad esempio, per valutare un voto:

# Valutazione di un voto
def valuta_voto(voto):
    if voto >= 9:
        return "Eccellente"
    elif voto >= 8:
        return "Ottimo"
    elif voto >= 7:
        return "Buono"
    elif voto >= 6:
        return "Sufficiente"
    else:
        return "Insufficiente"

# Esempio didattico per insegnare le leggi di Newton
def analizza_oggetto(massa, forza=None, accelerazione=None):
    """Utilizza la seconda legge di Newton: F = m * a"""
    if forza is None and accelerazione is not None:
        forza = massa * accelerazione
        return f"Un oggetto di massa {massa} kg con accelerazione {accelerazione} m/s² subisce una forza di {forza} N"
    elif accelerazione is None and forza is not None:
        accelerazione = forza / massa
        return f"Un oggetto di massa {massa} kg sottoposto a una forza di {forza} N acquisisce un'accelerazione di {accelerazione} m/s²"
    else:
        return "Fornire o la forza o l'accelerazione, ma non entrambe o nessuna"

Cicli (for e while)

Ciclo for

Il ciclo for si utilizza per ripetere un blocco di codice per ogni elemento di un elenco. Ad esempio, per stampare tutti gli elementi di una lista:

# Ciclo for per calcolare la somma dei primi n numeri
def somma_primi_n(n):
    somma = 0
    for i in range(1, n+1):
        somma += i
    return somma

# Calcolo del fattoriale
def fattoriale(n):
    if n < 0:
        return "Impossibile calcolare il fattoriale di un numero negativo"

    risultato = 1
    # Approccio iterativo
    for i in range(1, n+1):
        risultato *= i
    return risultato
Ciclo while

Il ciclo while si utilizza per ripetere un blocco di codice finché non venga verificata una condizione. Ad esempio, per calcolare il massimo comun divisore (MCD) tra due numeri:

# Ciclo while per la ricerca del massimo comun divisore (algoritmo di Euclide)

def mcd(a, b):
    while b:
        a, b = b, a % b
    return a

Risoluzione di problemi step-by-step con Python

La programmazione permette di affrontare problemi complessi scomponendoli in passaggi più semplici. In questo modo, il problema viene suddiviso in una serie di passaggi logici che possono essere facilmente compresi e risolti. I problemi più complessi possono essere suddivisi in sottoproblemi più semplici che possono essere risolti indipendentemente e successivamente combinati per ottenere la soluzione finale.

# Esempio: risoluzione di un'equazione di secondo grado
def risolvi_equazione_secondo_grado(a, b, c):
    """Risolve un'equazione nella forma ax² + bx + c = 0"""
    # Calcolo del discriminante
    delta = b**2 - 4*a*c

    # Verifica solubilità e calcolo soluzioni
    if delta < 0:
        return "L'equazione non ha soluzioni reali"
    elif delta == 0:
        x = -b / (2*a)
        return f"L'equazione ha un'unica soluzione: x = {x}"
    else:
        x1 = (-b + (delta)**0.5) / (2*a)
        x2 = (-b - (delta)**0.5) / (2*a)
        return f"L'equazione ha due soluzioni: x₁ = {x1} e x₂ = {x2}"

# Esempio di applicazione
print(risolvi_equazione_secondo_grado(1, -3, 2))  # x₁ = 2 e x₂ = 1

Relazione tra concetti di programmazione e insegnamento delle scienze

La programmazione fornisce strumenti potenti per l'insegnamento delle scienze, come ad esempio:

  • La rappresentazione di concetti astratti come funzioni, classi e oggetti
  • La simulazione di fenomeni reali come ad esempio il moto uniformemente accelerato
  • L'analisi di dati sperimentali e la visualizzazione di risultati
# Esempio: simulazione del moto uniformemente accelerato
def posizione_moto_accelerato(pos_iniziale, vel_iniziale, accelerazione, tempo):
    """
    Calcola la posizione di un oggetto in moto uniformemente accelerato
    usando l'equazione: x = x₀ + v₀t + (1/2)at²
    """
    return pos_iniziale + vel_iniziale * tempo + 0.5 * accelerazione * tempo**2

# Simulazione del movimento
def simula_caduta_libera(altezza_iniziale, durata=10, step=0.5):
    """Simula la caduta libera di un oggetto partendo da un'altezza data"""
    g = 9.81  # accelerazione di gravità (m/s²)

    print("Tempo (s) | Altezza (m) | Velocità (m/s)")
    print("-" * 40)

    for t in range(int(durata/step) + 1):
        tempo = t * step
        altezza = posizione_moto_accelerato(altezza_iniziale, 0, -g, tempo)
        velocita = 0 + (-g) * tempo  # v = v₀ + at

        if altezza <= 0:
            print(f"{tempo:.1f}      | {0:.2f}        | {velocita:.2f}")
            print(f"L'oggetto ha toccato il suolo dopo {tempo:.1f} secondi")
            break

        print(f"{tempo:.1f}      | {altezza:.2f}        | {velocita:.2f}")

# Esempio di utilizzo
# simula_caduta_libera(100)  # Simulazione di caduta da 100m

Generazione di valori casuali

Il modulo random in Python è utilizzato per generare numeri casuali. In particolare, la funzione random.randint(a, b) restituisce un numero intero casuale compreso tra a e b (estremi inclusi).

Ad esempio, se si vuole simulare il lancio di un dado a sei facce, si può utilizzare la seguente istruzione:

import random

dado = random.randint(1, 6)
print(dado)

In questo modo, la variabile dado conterrà un numero intero casuale compreso tra 1 e 6.

Il modulo random utilizza un algoritmo di generazione di numeri casuali che è sufficientemente buono per la maggior parte delle applicazioni, ma non è adatto per applicazioni che richiedono una elevata sicurezza o precisione, come ad esempio la crittografia o la simulazione di eventi fisici.

Esercizi: Mini-progetti di coding

1. Esercizio guidato: Calcolatrice scientifica semplice

import math

def calcolatrice():
    print("Calcolatrice Scientifica")
    print("Operazioni disponibili:")
    print("1. Addizione (+)")
    print("2. Sottrazione (-)")
    print("3. Moltiplicazione (*)")
    print("4. Divisione (/)")
    print("5. Potenza (^)")
    print("6. Radice quadrata (sqrt)")
    print("7. Seno (sin)")
    print("8. Coseno (cos)")
    print("9. Logaritmo naturale (ln)")

    scelta = input("Scegli un'operazione (1-9): ")

    if scelta in ['1', '2', '3', '4', '5']:
        a = float(input("Inserisci il primo numero: "))
        b = float(input("Inserisci il secondo numero: "))

        if scelta == '1':
            risultato = a + b
            operazione = f"{a} + {b}"
        elif scelta == '2':
            risultato = a - b
            operazione = f"{a} - {b}"
        elif scelta == '3':
            risultato = a * b
            operazione = f"{a} * {b}"
        elif scelta == '4':
            if b == 0:
                return "Errore: divisione per zero"
            risultato = a / b
            operazione = f"{a} / {b}"
        elif scelta == '5':
            risultato = a ** b
            operazione = f"{a} ^ {b}"

    elif scelta in ['6', '7', '8', '9']:
        a = float(input("Inserisci un numero: "))

        if scelta == '6':
            if a < 0:
                return "Errore: radice di numero negativo"
            risultato = math.sqrt(a)
            operazione = f"sqrt({a})"
        elif scelta == '7':
            # Converte in radianti se l'input è in gradi
            angolo = math.radians(a)
            risultato = math.sin(angolo)
            operazione = f"sin({a}°)"
        elif scelta == '8':
            angolo = math.radians(a)
            risultato = math.cos(angolo)
            operazione = f"cos({a}°)"
        elif scelta == '9':
            if a <= 0:
                return "Errore: logaritmo di numero non positivo"
            risultato = math.log(a)
            operazione = f"ln({a})"

    else:
        return "Scelta non valida"

    return f"{operazione} = {risultato}"

# Per eseguire la calcolatrice:
# print(calcolatrice())

Soluzione passo-passo:

  1. Importiamo il modulo math per le funzioni matematiche
  2. Definiamo una funzione calcolatrice() che mostra un menu di operazioni
  3. Chiediamo all'utente di scegliere un'operazione numerica
  4. A seconda dell'operazione scelta, chiediamo uno o due operandi
  5. Eseguiamo l'operazione matematica selezionata
  6. Restituiamo il risultato formattato

2. Esercizio semi-guidato: Analisi statistica di una serie di dati

Problema: Crea un programma che calcoli media, mediana, moda, deviazione standard e range di un insieme di valori.

Suggerimenti:

  • Usa le liste per memorizzare i dati
  • Puoi calcolare la media come somma di tutti i valori diviso il numero di valori
  • Per la mediana, ordina la lista e prendi il valore centrale (o la media dei due centrali se la lunghezza è pari)
  • Per la moda, conta le occorrenze di ciascun valore e trova quello con conteggio maggiore
  • La deviazione standard è la radice della media dei quadrati delle differenze dalla media
def analisi_statistica(dati):
    # Controllo input
    if not dati:
        return "Errore: nessun dato fornito"

    # Media
    media = sum(dati) / len(dati)

    # Mediana
    dati_ordinati = sorted(dati)
    n = len(dati)
    if n % 2 == 0:
        mediana = (dati_ordinati[n//2 - 1] + dati_ordinati[n//2]) / 2
    else:
        mediana = dati_ordinati[n//2]

    # Moda (può esserci più di una moda)
    conteggi = {}
    for valore in dati:
        if valore in conteggi:
            conteggi[valore] += 1
        else:
            conteggi[valore] = 1

    max_conteggio = max(conteggi.values())
    moda = [k for k, v in conteggi.items() if v == max_conteggio]

    # Deviazione standard
    somma_scarti_quadrati = sum((x - media) ** 2 for x in dati)
    deviazione_standard = (somma_scarti_quadrati / n) ** 0.5

    # Range (differenza tra massimo e minimo)
    range_dati = max(dati) - min(dati)

    return {
        "media": media,
        "mediana": mediana,
        "moda": moda if len(moda) < len(dati) else "Nessuna moda significativa",
        "deviazione_standard": deviazione_standard,
        "range": range_dati,
        "minimo": min(dati),
        "massimo": max(dati),
        "conteggio": len(dati)
    }

# Esempio di utilizzo:
# voti = [8, 7, 9, 6, 7, 8, 9, 8, 10, 7]
# risultati = analisi_statistica(voti)
# for chiave, valore in risultati.items():
#     print(f"{chiave}: {valore}")

3. Esercizio aperto: Simulatore di lancio di dadi

Problema: Crea un simulatore che lanci un numero specificato di dadi con un numero specificato di facce e analizzi la distribuzione dei risultati.

import random
import matplotlib.pyplot as plt

def lancia_dadi(n_dadi, n_facce, n_lanci):
    """
    Simula il lancio di n_dadi dadi con n_facce facce ciascuno per n_lanci volte.
    Restituisce un dizionario con le statistiche dei lanci.
    """
    # Implementa la tua soluzione qui
    pass

# Esempio atteso:
# risultati = lancia_dadi(2, 6, 1000)
# Dovrebbe restituire statistiche su 1000 lanci di 2 dadi a 6 facce

4. Mini-progetto: Convertitore di unità di misura per fisica

Problema: Crea un programma che converta tra diverse unità di misura utili per la fisica (lunghezza, massa, tempo, temperatura, ecc.).

def converti_unita(valore, da_unita, a_unita):
    """
    Converte un valore da un'unità di misura a un'altra.

    Parametri:
    valore -- il valore numerico da convertire
    da_unita -- l'unità di misura di partenza (es. "m", "km", "kg", ecc.)
    a_unita -- l'unità di misura di arrivo

    Restituisce:
    Il valore convertito nella nuova unità di misura
    """
    # Implementa la tua soluzione qui
    pass

# Esempio atteso:
# conversione = converti_unita(1, "km", "m")
# Dovrebbe restituire 1000.0

5. Mini-progetto: Programma per matematica finanziaria

Problema: Crea un semplice programma che calcoli l'interesse composto.

def calcola_interesse_composto(capitale_iniziale, tasso_interesse, anni, versamenti_annuali=0):
    """
    Calcola il capitale finale con interesse composto

    Parametri:
    capitale_iniziale -- la somma iniziale investita
    tasso_interesse -- il tasso di interesse annuale (espresso come decimale, es. 0.05 per 5%)
    anni -- il numero di anni dell'investimento
    versamenti_annuali -- versamenti aggiuntivi annuali (opzionale)

    Restituisce:
    Il capitale finale dopo gli anni specificati
    """
    # Implementa la tua soluzione qui
    pass

# Esempio atteso:
# capitale_finale = calcola_interesse_composto(1000, 0.05, 10)
# Dovrebbe restituire circa 1628.89 (1000 × 1.05^10)

Risorse aggiuntive

Documentazione online

Libri consigliati

  • "Il Tutorial di Python" di Guido van Rossum
  • "Python Crash Course" di Eric Matthes
  • "Pensare in Python. Come pensare da informatico" di Allen Downey

Comunità e forum