In questa lezione impari a definire funzioni in Python con la parola chiave def, a passare parametri (posizionali e per parola‑chiave), a usare return per restituire valori e a scrivere esempi pratici chiari e riusabili. Capirai perché le funzioni rendono il codice più leggibile, testabile e manutenibile, come documentarle con docstring e come evitare errori comuni (es. confondere print() con return).
🔗 Ripassi consigliati (interni):
• Lezione 2 – Il tuo primo script: Hello, Python! → https://www.saperesemplice.com/primo-script-python-hello/
• Lezione 3 – Variabili e Tipi di Dato → https://www.saperesemplice.com/variabili-tipi-dato-python/
• Lezione 9 – Cicloforerange()→ https://www.saperesemplice.com/ciclo-for-range-python/
• Lezione 6 – Condizioni conif,else,elif→ https://www.saperesemplice.com/condizioni-if-else-elif-python/
Dettagli lezione
⏱️ Tempo stimato: 35–45 minuti
🧩 Difficoltà: Facile
🎯 Obiettivi specifici
- Definire funzioni con
def nome(par1, par2, ...)e comprendere parametri vs argomenti. - Usare
returnper restituire valori (incluso ritorno di più valori tramite tuple). - Comprendere parametri posizionali e per parola‑chiave (keyword arguments).
- Scrivere funzioni pure e riusabili con docstring e nomi snake_case.
- Applicare i concetti in esempi pratici e un esercizio step‑by‑step.
🧱 Perché definire funzioni
Le funzioni incapsulano istruzioni in un blocco riutilizzabile. Vantaggi:
- Riuso: scrivi una volta, usi ovunque.
- Astrazione: nascondi i dettagli, esponi un nome chiaro.
- Testabilità: puoi testare la funzione isolatamente.
- Ordine: il codice è più corto e leggibile.
# Sintassi base
# def <nome>(<parametri>...):
# <blocco>
# return <valore_opzionale>
def greet(name):
"""Return a welcome message for the given name."""
return f"Hello, {name}!"
print(greet("Alice")) # Hello, Alice!
💡 Usa snake_case per i nomi delle funzioni:
calculate_total,send_email. Evita nomi generici comedo().
Domanda per te: quale funzionalità ripeti spesso nei tuoi script e potresti incapsulare in una funzione?
🔎 Parametri e argomenti
Parametro: il nome nella definizione della funzione.
- Argomento: il valore passato in chiamata.
def area_rect(width, height):
return width * height
# Argomenti posizionali
print(area_rect(3, 5)) # 15
# Argomenti per parola‑chiave (keyword)
print(area_rect(height=5, width=3)) # 15 (ordine libero)
✨ Suggerimento leggibilità: quando una funzione ha molti parametri, privilegia chiamate per parola‑chiave:
send_email(to="...", subject="...").
Errore comune da evitare
Passare lo stesso argomento due volte (posizionale e keyword):
f(1, x=1)→TypeError: got multiple values for argument 'x'.
🔁 return: restituire valori (anche multipli)
return <expr>termina la funzione e restituisce il valore.returnsenza espressione restituisceNone.- Se non scrivi
return, Python restituisceNonealla fine.
def divide(a, b):
if b == 0:
return None # oppure: raise ZeroDivisionError
return a / b
result = divide(10, 2)
print(result) # 5.0
Ritornare più valori
In Python è naturale restituire più valori come tupla e spacchettarli con l’unpacking.
def stats(numbers):
total = sum(numbers)
count = len(numbers)
average = total / count if count else 0
return total, count, average # tuple
s, n, avg = stats([3, 7, 10])
print(s, n, avg) # 20 3 6.666...
Domanda per te: quando preferiresti restituire un dizionario invece di una tupla?
🧰 Documentare le funzioni con docstring
Una docstring è una stringa all’inizio del corpo della funzione che spiega cosa fa, parametri, ritorno e note.
def fahrenheit_to_celsius(f):
"""Convert Fahrenheit to Celsius.
Args:
f (float): Temperature in Fahrenheit.
Returns:
float: Temperature in Celsius.
"""
return (f - 32) * 5/9
print(fahrenheit_to_celsius.__doc__.splitlines()[0]) # Convert Fahrenheit to Celsius.
🧑🏫 Best practice: una riga di sommario concisa; per docstring lunghe, una riga vuota e poi i dettagli.
🔶 Esempi pratici
1) Normalizza un nome (strip, title)
def normalize_name(raw):
"""Return a cleaned display name."""
return raw.strip().title()
print(normalize_name(" aLiCe ")) # Alice
2) Somma dei numeri da 1 a n
def sum_to(n):
"""Return the sum from 1 to n inclusive."""
total = 0
for i in range(1, n + 1):
total += i
return total
print(sum_to(5)) # 15
3) Formatta un prezzo con valuta
def format_price(amount, currency="€"):
"""Return a formatted price like '€12.50'."""
return f"{currency}{amount:.2f}"
print(format_price(12.5)) # €12.50
print(format_price(12.5, "$")) # $12.50
4) Validazione semplice (ritorno booleano + messaggio)
def is_strong_password(pwd):
"""Return True if password meets minimal criteria, else False."""
return len(pwd) >= 8 and any(c.isdigit() for c in pwd)
if is_strong_password("abc12345"):
print("Password accepted")
else:
print("Weak password")
💬 Domanda per il lettore: nelle funzioni 2–4, dove useresti parametri per parola‑chiave per aumentare la chiarezza della chiamata?
🧠 print() non è return: cosa cambia?
print()mostra un testo (effetto collaterale), non restituisce il risultato da riusare.returnpassa un valore al chiamante che può essere salvato, testato, combinato.
def bad_add(a, b):
print(a + b) # side-effect only
x = bad_add(2, 3) # stampa 5 ma x è None
print(x) # None
# ✔️ Corretto
def add(a, b):
return a + b
x = add(2, 3)
print(x) # 5
Errore comune da evitare
Scrivere funzioni che stampano invece di ritornare. Preferisci
returne lascia al chiamante la responsabilità di stampare.
🧭 Parametri facili da leggere: consigli veloci
- Dai nomi parlanti ai parametri (
width,height,tax_rate). - Evita di riusare nomi di built‑in (
list,sum,dict). - Ordina i parametri: prima quelli obbligatori, poi quelli opzionali (verranno approfonditi nella prossima lezione).
- Usa valori di ritorno chiari:
True/False, numeri, tuple o dict ben strutturati.
⚠️ Errore comune da evitare
Definire parametri opzionali con oggetti mutabili come valore di default (es.
def f(x, items=[])). Questo porta a stato condiviso tra chiamate.
Soluzione tipica: usaNonecome default e crea l’oggetto dentro la funzione. (Approfondiremo nella prossima lezione.)
# ❌ Sbagliato
# def append_user(user, users=[]):
# users.append(user)
# return users
# ✔️ Corretto
def append_user(user, users=None):
if users is None:
users = []
users.append(user)
return users
📖 Sezione teorica
- Definizione:
def nome(par1, ...)+ blocco indentato; primo statement opzionale: docstring. - Parametri/Argomenti: posizionali o keyword; non passare lo stesso parametro due volte.
return: termina la funzione; senza espressione o a fine funzione →None.- Ritorni multipli: usa tuple e unpacking.
- Stampa vs ritorno:
print()mostra,returnrestituisce. - Stile: nomi snake_case, docstring (PEP 257), leggibilità prima di tutto.
🔗 Riferimenti esterni:
• Python Tutorial – Defining Functions → https://docs.python.org/3/tutorial/controlflow.html#defining-functions
• PEP 8 – Style Guide (naming snake_case) → https://peps.python.org/pep-0008/
• PEP 257 – Docstring Conventions → https://peps.python.org/pep-0257/
📚 Glossario tecnico
- Parametro: nome formale nella definizione della funzione.
- Argomento: valore passato alla funzione in chiamata.
- Docstring: stringa di documentazione all’inizio del corpo della funzione.
📝 Esercizio finale
Realizza una piccola libreria di utilità con 3 funzioni e un main di prova.
Requisiti:
clean_email(s)→ restituisce l’email normalizzata (trim, minuscolo) oNonese non contiene@.apply_discount(price, rate)→ ritornapricescontato delrate(0–1).summary(nums)→ ritorna tuple(count, minimum, maximum, mean); se la lista è vuota, ritorna(0, None, None, 0).- Nel main, chiama le funzioni e stampa in inglese un mini‑report.
Schema d’aiuto:
def clean_email(s):
# Your code here...
...
def apply_discount(price, rate):
...
def summary(nums):
...
# Demo
print("-- Demo --")
print(clean_email(" [email protected] "))
print(apply_discount(100, 0.2))
print(summary([3, 7, 10]))
🧠 Quiz finale
Non guardare le risposte subito! Sono più sotto 👇
- Cosa fa la parola chiave
def?
A) Crea una variabile
B) Definisce una funzione
C) Converte una tupla in lista - Cosa restituisce una funzione senza
returnesplicito?
A)0
B) Stringa vuota
C)None - Quale chiamata è corretta con argomenti keyword?
A)area_rect(3, 5)
B)area_rect(width=3, height=5)
C)area_rect(3, height=5, width=3) - Cosa non dovresti fare nei nomi funzione?
A) Usaresnake_case
B) Usare nomi di built‑in comelist
C) Scrivere verbi/azioni (load_data) - La differenza tra
print()ereturnè che:
A)printrestituisce il valore al chiamante
B)returnstampa un valore
C)printmostra,returnrestituisce - Quale opzione descrive correttamente un parametro?
A) Il valore passato in chiamata
B) Il nome formale nella definizione
C) Una variabile globale - Qual è il modo pitonico per ritornare più valori?
A) Lista
B) Tupla (con eventuale unpacking)
C) Stringa con separatore - Quale riga causa
TypeError: got multiple values for argument?
A)f(x=1)
B)f(1)
C)f(1, x=1)
❓ FAQ
1) Posso definire una funzione dopo averla chiamata?
Il file viene eseguito top‑down: la funzione deve essere definita prima che il flusso arrivi alla chiamata. In REPL puoi definire e poi chiamare liberamente.
2) È meglio restituire una tupla o un dizionario?
Dipende: tupla per pochi valori con ordine chiaro; dizionario per etichette esplicite ({"sum": 10, "avg": 5}).
3) Le funzioni possono modificare gli argomenti?
Gli oggetti mutabili (liste, dict) possono essere modificati in‑place. Valuta se è desiderabile o se è meglio restituire una copia
4) Come scelgo i nomi delle funzioni?
Usa verbi chiari in snake_case (PEP 8). Esempi: load_data, normalize_text, send_email.
5) Come scrivo docstring efficaci?
Una riga di sommario, poi dettagli (parametri, ritorni, eccezioni). Vedi PEP 257.
🔗 Link utili
Esterni
• Defining Functions – Python Tutorial → https://docs.python.org/3/tutorial/controlflow.html#defining-functions
• PEP 8 – Style Guide (naming) → https://peps.python.org/pep-0008/
• PEP 257 – Docstring Conventions → https://peps.python.org/pep-0257/
SapereSemplice
• Lezione 2 – Primo script: Hello, Python → https://www.saperesemplice.com/primo-script-python-hello/
• Lezione 3 – Variabili e Tipi di Dato → https://www.saperesemplice.com/variabili-tipi-dato-python/
• Lezione 9 – Ciclo for e range → https://www.saperesemplice.com/ciclo-for-range-python/
• Lezione 6 – Condizioni con if/else/elif → https://www.saperesemplice.com/condizioni-if-else-elif-python/
🔁 Collegamento alla lezione successiva
➡️ Prosegui alla Lezione 14: Argomenti opzionali, scope e funzioni annidate
(Il link verrà inserito non appena l’articolo sarà online.)
🗨️ Hai dubbi? Lascia un commento!
📩 Vuoi il PDF della lezione? Scrivici!
🔗 Condividi con un compagno di corso.
🧪 Risposte del quiz
- B
- C
- B
- B
- C
- B
- B
- C
📅 Aggiornato il 04/09/2025
