Funzioni Python
Impara a definire e chiamare funzioni Python, usare parametri, argomenti predefiniti, *args, **kwargs, valori di ritorno, scope e docstring.
Una funzione è un blocco di codice riutilizzabile e con nome che esegue un compito specifico. Le funzioni ti permettono di scrivere la logica una sola volta e richiamarla da qualsiasi punto del programma, rendendo il codice più breve, più leggibile e più semplice da testare. Questo capitolo copre tutto ciò che ti serve per lavorare con sicurezza con le funzioni Python: definizione, parametri, valori di ritorno, argomenti predefiniti, *args e **kwargs, scope, docstring, type hint, ricorsione e utilizzo delle funzioni come oggetti di prima classe.
Definire una Funzione
Usa la parola chiave def, un nome, le parentesi e i due punti. Il corpo è indentato di un livello.
def greet(name):
print("Hello, " + name)La funzione non viene eseguita finché non la chiami. Al momento della definizione non accade nulla, tranne che Python memorizza l'oggetto funzione con il nome specificato.
Chiamare una Funzione
Passa gli argomenti tra le parentesi corrispondendo i nomi dei parametri della definizione.
Valori di Ritorno
Una funzione può restituire un risultato al chiamante con l'istruzione return. Senza return, Python restituisce None.
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 8Una volta eseguita l'istruzione return, la funzione si interrompe immediatamente — qualsiasi codice che la segue nello stesso corpo della funzione è irraggiungibile.
Restituire Più Valori
Python ti permette di restituire più valori come tupla, che puoi destrutturare sul lato chiamante.
import math
def circle_stats(radius):
area = math.pi * radius ** 2
circumference = 2 * math.pi * radius
return area, circumference
area, circ = circle_stats(5)
print(round(area, 2)) # 78.54
print(round(circ, 2)) # 31.42Parametri e Argomenti
| Termine | Significato |
|---|---|
| Parametro | Nome della variabile nella definizione della funzione |
| Argomento | Valore effettivo passato durante la chiamata alla funzione |
Python supporta diversi modi per passare argomenti.
Argomenti Posizionali
Gli argomenti vengono abbinati ai parametri in ordine.
def describe(name, age):
print(name, "is", age, "years old")
describe("Bob", 25) # Bob is 25 years oldArgomenti per Nome (Keyword Arguments)
Puoi passare argomenti specificando il nome, in qualsiasi ordine.
describe(age=25, name="Bob") # Bob is 25 years oldValori Predefiniti dei Parametri
Fornisce un valore di fallback che viene usato quando il chiamante omette quell'argomento.
def greet(name="World"):
print("Hello, " + name)
greet() # Hello, World
greet("Alice") # Hello, AliceAttenzione: non usare mai un oggetto mutabile (lista, dict) come valore predefinito — viene creato una sola volta al momento della definizione e condiviso tra tutte le chiamate. Usa None come valore predefinito e crea l'oggetto all'interno del corpo della funzione.
# Correct pattern for a mutable default
def append_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lstArgomenti Posizionali Arbitrari (*args)
Anteponi * al nome di un parametro per raccogliere un numero qualsiasi di argomenti posizionali in una tupla.
def total(*numbers):
return sum(numbers)
print(total(1, 2, 3)) # 6
print(total(10, 20)) # 30Argomenti per Nome Arbitrari (**kwargs)
Anteponi ** per raccogliere un numero qualsiasi di argomenti per nome in un dizionario.
def describe_person(**info):
for key, value in info.items():
print(key + ": " + str(value))
describe_person(name="Alice", age=30, city="Paris")
# name: Alice
# age: 30
# city: ParisCombinare i Tipi di Parametri
Quando mescoli tipi di parametri, l'ordine deve essere: posizionali, *args, solo per nome, **kwargs.
def log(level, *messages, separator=" | ", **meta):
print(level.upper(), separator.join(messages), meta)
log("info", "started", "ready", separator=" — ", version="1.0")
# INFO started — ready {'version': '1.0'}Scope delle Variabili
Le regole di scoping di Python seguono la regola LEGB: Local → Enclosing → Global → Built-in.
Una variabile definita all'interno di una funzione è locale — non è accessibile dall'esterno.
def my_func():
x = 10 # local to my_func
print(x)
my_func()
# print(x) # NameError: name 'x' is not definedPer leggere o modificare una variabile globale all'interno di una funzione, dichiarala con global.
x = 10
def change_x():
global x
x = 20
change_x()
print(x) # 20Usa global con parsimonia — le funzioni che dipendono dallo stato globale sono più difficili da testare e riutilizzare. Consulta Python Variables e Global Variables per un approfondimento sullo scope.
Docstring
Una docstring è una stringa letterale collocata immediatamente dopo la riga def. Documenta cosa fa la funzione, cosa accetta e cosa restituisce. Python la memorizza nell'attributo __doc__ della funzione e strumenti come help() la visualizzano.
def add(a, b):
"""Return the sum of a and b.
Args:
a: First number.
b: Second number.
Returns:
The sum as a number.
"""
return a + b
print(add.__doc__)
# Return the sum of a and b.
# ...Type Hint
I type hint (PEP 484) ti permettono di annotare i tipi dei parametri e del valore di ritorno. Python non li verifica a runtime, ma editor, linter e mypy li usano per individuare i bug in anticipo.
def multiply(a: float, b: float) -> float:
return a * b
print(multiply(3, 4)) # 12
print(multiply(2.5, 2.0)) # 5.0Ricorsione
Una funzione può chiamare se stessa. Questo si chiama ricorsione ed è utile per problemi con una struttura naturalmente ricorsiva (alberi, fattoriali, ecc.). Ogni funzione ricorsiva ha bisogno di un caso base che arresti la ricorsione.
def factorial(n):
if n == 0 or n == 1: # base case
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
print(factorial(0)) # 1Python limita la profondità di ricorsione (predefinita a 1000) per prevenire stack overflow. Per ricorsioni profonde, preferisci un approccio iterativo o usa sys.setrecursionlimit.
Funzioni come Oggetti di Prima Classe
In Python, le funzioni sono oggetti. Puoi memorizzarle in variabili, passarle come argomenti e restituirle da altre funzioni.
def apply(func, value):
return func(value)
def double(n):
return n * 2
print(apply(double, 7)) # 14Questa è la base per le funzioni lambda, le funzioni di ordine superiore e i decoratori.
Funzioni Built-in vs. Funzioni Definite dall'Utente
Python include molte funzioni built-in — print(), len(), range(), sum(), sorted() — sempre disponibili senza alcun import. Le funzioni definite dall'utente sono quelle che scrivi con def. Entrambe seguono una sintassi di chiamata identica.
Buone Pratiche
- Dai alle funzioni nomi che siano verbi:
calculate_tax()è più chiaro ditax(). - Fai una cosa sola: una funzione che valida, salva e invia un'email sono tre funzioni che aspettano di nascere.
- Scrivi una docstring: anche una sola frase che descriva lo scopo è preziosa.
- Evita gli effetti collaterali dove possibile: le funzioni che restituiscono valori e non modificano lo stato globale sono più facili da testare.
- Mantieni le firme brevi: più di tre o quattro parametri è un segnale per raggruppare i dati correlati in una classe o un dict.
- Usa i type hint: fungono da documentazione leggera e abilitano l'analisi statica.