1. Home
  2. iThink
  3. Programmazione per Ragazzi
  4. Funzioni in Python: scriverle, chiamarle, riusarle
Programmazione per Ragazzi Divento Programmatore · Capitolo 4

Funzioni in Python: scriverle, chiamarle, riusarle

Codice Python sullo schermo di un computer
Foto: JohnsonMartin · Pixabay · Licenza dei contenuti Pixabay

Divento Programmatore — Capitolo 4: Funzioni

Hai scritto codice che decide (Cap. 3) e ripete (cicli). Ora impari a incapsulare logica in blocchi riutilizzabili: le funzioni. È il salto da "script" a "programma vero".

Cosa imparerai

| Concetto | Descrizione | | ---------- | ------------- | | def | Parola chiave per definire una funzione | | Parametri | Input della funzione (placeholders) | | Argomenti | Valori reali passati alla chiamata | | return | Output: restituisce valore al chiamante | | Scope | Dove le variabili "vivono" (locale vs globale) | | Docstring | Documentazione integrata ("""...""") | | DRY | Don't Repeat Yourself — principio chiave |


1. Perché le funzioni? L'analogia della ricetta

Una ricetta dice: "Prendi ingredienti, fai passi, ottieni piatto". La usi quante volte vuoi.

# SENZA funzione (ripetizione = male)
print("=== MENU ===")
print("1. Pizza")
print("2. Pasta")
print("3. Insalata")
print("==============")

# ... 50 righe dopo ...
print("=== MENU ===")
print("1. Pizza")
print("2. Pasta")
print("3. Insalata")
print("==============")
# CON funzione (DRY = bene)
def mostra_menu():
    print("=== MENU ===")
    print("1. Pizza")
    print("2. Pasta")
    print("3. Insalata")
    print("==============")

mostra_menu()  # Chiama la funzione
# ... 50 righe dopo ...
mostra_menu()  # Riutilizza!

Regola d'oro: Se copi-incolli codice → trasformalo in funzione.


2. Anatomia di una funzione

def saluta(nome: str) -> str:
    """Restituisce un saluto personalizzato.
    
    Args:
        nome: Nome della persona da salutare.
    
    Returns:
        Stringa di saluto formattata.
    """
    messaggio = f"Ciao, {nome}!"   # Variabile LOCALE
    return messaggio               # Esce e restituisce valore

# Uso
risultato = saluta("Alex")
print(risultato)   # Ciao, Alex!

Parti obbligatorie

| Parte | Esempio | Note | | ------- | --------- | ------ | | def | def saluta( | Parola chiave | | Nome | saluta | snake_case, verbo | | Parametri | (nome: str) | Tra parentesi, opzionali | | : | ): | Due punti finali | | Corpo | messaggio = ... | Indentato 4 spazi | | return | return messaggio | Opzionale (default None) |

Type hints (opzionali ma consigliati)

def area_rettangolo(base: float, altezza: float) -> float:
    return base * altezza
  • base: float = parametro atteso float
  • -> float = tipo di ritorno
  • Non enforced a runtime, ma aiutano editor e lettori

3. Parametri e argomenti

Posizionali (ordine conta)

def presenta(nome, eta, citta):
    print(f"{nome}, {eta} anni, da {citta}")

presenta("Luna", 13, "Roma")     # OK
presenta("Roma", 13, "Luna")     # Logica sbagliata, ma sintassi OK

Named (keyword arguments) — ordine NON conta

presenta(nome="Luna", citta="Roma", eta=13)
presenta(citta="Roma", nome="Luna", eta=13)  # Uguale

Valori di default (parametri opzionali)

def saluta(nome, saluto="Ciao"):
    print(f"{saluto}, {nome}!")

saluta("Alex")           # Ciao, Alex!
saluta("Alex", "Ehi")    # Ehi, Alex!
saluta(nome="Sam")       # Ciao, Sam!
saluta(saluto="Hey", nome="Sam")  # Hey, Sam!

Regola: Parametri con default dopo quelli senza.

# OK
def f(a, b=1, c=2): pass
# ERRORE
def f(a=1, b): pass      # SyntaxError

*args e **kwargs (anticipazione avanzata)

def somma(*numeri):          # Tupla di positional args
    return sum(numeri)

def configura(**opzioni):    # Dizionario di keyword args
    for k, v in opzioni.items():
        print(f"{k} = {v}")

somma(1, 2, 3, 4)            # 10
configura(volume=80, fullscreen=True, difficulty="hard")

4. Return: restituire valori

def quadrato(x):
    return x * x

risultato = quadrato(5)   # risultato = 25
print(quadrato(7))        # Stampa 49 direttamente

Return multipli (tupla)

def min_max(lista):
    return min(lista), max(lista)

minimo, massimo = min_max([3, 1, 4, 1, 5])
print(minimo, massimo)   # 1 5

Return anticipato (guard clause)

def dividi(a, b):
    if b == 0:
        return None      # Esce subito, evita errore
    return a / b

Funzioni senza return → restituiscono None

def stampa_due_volte(testo):
    print(testo)
    print(testo)

risultato = stampa_due_volte("Hey")
print(risultato)   # None

5. Scope: dove vivono le variabili

Locale (dentro funzione)

def foo():
    x = 10        # Locale a foo()
    print(x)

foo()             # 10
print(x)          # NameError! x non esiste qui

Globale (fuori funzioni)

GIOCATORE = "Alex"   # Globale (convenzione: MAIUSCOLO)

def saluta():
    print(GIOCATORE)  # Legge globale OK

saluta()             # Alex

Modificare globale (serve global)

punteggio = 0

def aggiungi_punti(p):
    global punteggio
    punteggio += p

aggiungi_punti(10)
print(punteggio)   # 10

Best practice: Evita global. Passa valori come parametri, restituisci risultati. Funzioni pure = stesso input → stesso output, niente effetti collaterali.

Shadowing (variabile locale nasconde globale)

nome = "Globale"

def test():
    nome = "Locale"   # Nuova variabile locale
    print(nome)       # Locale

test()                # Locale
print(nome)           # Globale (invariata)

6. Docstring: documenta le tue funzioni

def calcola_danno(attacco: int, difesa: int, critico: bool = False) -> int:
    """Calcola danno finale considerando attacco, difesa e critico.
    
    Formula: max(1, attacco - difesa) * (2 se critico else 1)
    
    Args:
        attacco: Valore attacco attaccante (>= 0).
        difesa: Valore difesa bersaglio (>= 0).
        critico: True se colpo critico (default False).
    
    Returns:
        Danno intero >= 1.
    
    Esempio:
        >>> calcola_danno(10, 3, True)
        14
    """
    base = max(1, attacco - difesa)
    return base * (2 if critico else 1)

Formato consigliato: Google Style o NumPy. Thonny mostra docstring con Ctrl+Shift+Spazio o hover.


7. Funzioni come "ricette" per i giochi

Esempio: sistema combattimento

import random

def tira_dado(facce: int = 6) -> int:
    """Simula lancio dado."""
    return random.randint(1, facce)

def calcola_colpo(attacco: int, precisione: int) -> bool:
    """True se colpo va a segno."""
    tiro = tira_dado(20)
    return tiro <= precisione

def calcola_danno(base: int, arma: str) -> int:
    """Danno base + bonus arma."""
    bonus = {"spada": 3, "ascia": 5, "arco": 2, "pugnale": 1}
    return base + bonus.get(arma, 0)

def attacca(nome: str, attacco: int, precisione: int, arma: str) -> str:
    """Esegue un attacco e restituisce messaggio."""
    if calcola_colpo(attacco, precisione):
        dmg = calcola_danno(attacco, arma)
        return f"🎯 {nome} colpisce con {arma}! Danno: {dmg}"
    else:
        return f"💨 {nome} manca il bersaglio!"

# Uso
print(attacca("Guerriero", 12, 14, "spada"))
print(attacca("Arciere", 10, 16, "arco"))

8. Script completo: Calcolatrice modulare

# calcolatrice.py
"""Calcolatrice a funzioni: ogni operazione è una funzione."""

def somma(a: float, b: float) -> float:
    return a + b

def differenza(a: float, b: float) -> float:
    return a - b

def prodotto(a: float, b: float) -> float:
    return a * b

def divisione(a: float, b: float) -> float | None:
    if b == 0:
        return None
    return a / b

def potenza(a: float, b: float) -> float:
    return a ** b

OPERAZIONI = {
    "1": ("Somma", somma, "+"),
    "2": ("Differenza", differenza, "-"),
    "3": ("Prodotto", prodotto, "*"),
    "4": ("Divisione", divisione, "/"),
    "5": ("Potenza", potenza, "**"),
}

def menu() -> str:
    print("\n=== CALCOLATRICE ===")
    for k, (nome, _, _) in OPERAZIONI.items():
        print(f"{k}. {nome}")
    print("0. Esci")
    return input("Scegli: ")

def main():
    while True:
        scelta = menu()
        if scelta == "0":
            print("Arrivederci!")
            break
        if scelta not in OPERAZIONI:
            print("Opzione non valida.")
            continue
        
        nome, func, simbolo = OPERAZIONI[scelta]
        try:
            a = float(input("Primo numero: "))
            b = float(input("Secondo numero: "))
        except ValueError:
            print("Inserisci numeri validi.")
            continue
        
        risultato = func(a, b)
        if risultato is None:
            print("Errore: divisione per zero!")
        else:
            print(f"Risultato: {a} {simbolo} {b} = {risultato}")

if __name__ == "__main__":
    main()

Nuovo pattern: if __name__ == "__main__": — il codice sotto gira solo se esegui il file direttamente, non se lo importi. Fondamentale per moduli (Cap. 6).


9. Tabella riassuntiva: checklist funzione ben fatta

| ✅ Controllo | Descrizione | | -------------- | ------------- | | Nome verbo | calcola_, ottieni_, valida_, disegna_ | | Un compito solo | Funzione fa UNA cosa bene | | Parametri tipizzati | def f(x: int) -> bool: | | Docstring | Cosa fa, args, return, esempio | | No side effects | Non modifica globali, non stampa (salvo funzioni I/O) | | Return esplicito | return valore non return nudo | | Testabile | Stesso input → stesso output |


10. Esercizi pratici

  1. Fattoriale: def fattoriale(n: int) -> int: (ricorsivo o iterativo)
  2. Primo: def e_primo(n: int) -> bool:
  3. Password generator: def genera_password(lunghezza: int = 12) -> str:
  4. Validazione email: def email_valida(email: str) -> bool: (usa @ e .)
  5. Refactoring: Prendi script Cap. 3 (Indovina numero) e spezza in funzioni: gioca_partita(), chiedi_numero(), dai_hint()

11. Checklist fine capitolo

  • [ ] Scrivi def nome_funzione(parametri) -> tipo:
  • [ ] Usi parametri posizionali, named, e con default
  • [ ] Restituisci valori con return
  • [ ] Capisci scope locale vs globale (evita global)
  • [ ] Scrivi docstring Google/NumPy style
  • [ ] Applichi DRY: nessuna copia-incolla di logica
  • [ ] Conosci if __name__ == "__main__":

Prossimo capitolo

Capitolo 5: Liste e dizionari — Collezioni di dati: ordinate (liste) e chiave-valore (dizionari). Operazioni, indexing, slicing, metodi, nesting, loop su collezioni.

👉 Leggi il Capitolo 5 →


Serie "Divento Programmatore: Python e i Giochi" (Cervello Elettronico Vol.2). Codice completo, tabelle, esercizi. Target 10-14 anni + guide adulti.

Per approfondire

Condividi LinkedIn Facebook X WhatsApp
Continua a leggere

Tutti gli articoli del blog

Strumenti gratuiti