Salta al contenuto
Note per Studenti Funzioni in Python

Funzioni in Python

In questa pagina 8

Definizione e chiamata

python
def area_rettangolo(base, altezza):
    """Restituisce l'area di un rettangolo."""
    return base * altezza

a = area_rettangolo(3, 4)      # 12

Parametri

python
def saluta(nome, saluto="Ciao", punto="!"):
    return f"{saluto}, {nome}{punto}"

saluta("Ada")                       # posizionale
saluta("Ada", "Buongiorno")
saluta("Ada", punto=".")            # argomento con nome (keyword)
  • I parametri con valore predefinito vanno dopo quelli senza.
  • *args raccoglie gli argomenti posizionali in più in una tupla; **kwargs quelli con nome in un dizionario.
python
def somma(*numeri):
    tot = 0
    for x in numeri:
        tot += x
    return tot

somma(1, 2, 3)      # 6

Trappola: default mutabile

Il valore predefinito viene valutato una volta sola, alla definizione:

python
def aggiungi(x, lista=[]):      # SBAGLIATO: la stessa lista è condivisa tra le chiamate
    lista.append(x)
    return lista

def aggiungi(x, lista=None):    # corretto
    if lista is None:
        lista = []
    lista.append(x)
    return lista

Passaggio degli argomenti

Python passa riferimenti a oggetti (call by object reference): il parametro diventa un nuovo nome per lo stesso oggetto dell'argomento.

  • Riassegnare il parametro non tocca il chiamante.
  • Modificare sul posto un argomento mutabile è visibile al chiamante.
python
def f(n, lista):
    n += 1              # rilega il nome locale n: il chiamante non lo vede
    lista.append(0)     # modifica l'oggetto condiviso: il chiamante lo vede

a, b = 5, [1]
f(a, b)
print(a, b)             # 5 [1, 0]

Confronto con il C (passaggio per valore e puntatori): Funzioni in CDefinizione e prototipo di una funzione C, tipo di ritorno e void, passaggio dei parametri sempre per valore, variabili locali, globali e static, file header e compilazione separata, funzioni ricorsive.Funzioni in C →.

Ambito delle variabili (scope)

Un nome viene cercato nell'ordine LEGB: Locale (funzione corrente) → Enclosing (funzioni che la contengono) → Globale (modulo) → Built-in.

  • Ogni nome assegnato dentro una funzione è locale a quella funzione, salvo dichiarazione global (o nonlocal).
  • Leggere una globale da una funzione è lecito; assegnarla senza global crea una locale.
python
contatore = 0
def incrementa():
    global contatore     # senza questa riga: UnboundLocalError
    contatore += 1

Le variabili globali modificate da funzioni rendono il codice difficile da seguire: meglio passare parametri e restituire valori.

Documentazione e tipi

python
def media(valori: list[float]) -> float:
    """Media aritmetica di una lista non vuota."""
    return sum(valori) / len(valori)
  • La docstring è la prima stringa del corpo; la mostra help(media).
  • Le annotazioni di tipo (type hint) sono documentazione verificabile da strumenti esterni (Pylance, mypy): l'interprete non le controlla.

Funzioni come oggetti e lambda

Le funzioni si possono assegnare, passare come argomenti e restituire.

python
def applica(f, x):
    return f(x)

applica(abs, -3)                        # 3
quadrato = lambda x: x * x              # funzione anonima di una sola espressione
sorted(parole, key=len)                 # ordina per lunghezza
sorted(studenti, key=lambda s: s[1])    # ordina tuple per il secondo campo

Progettare funzioni

Errori tipici

  • Dimenticare return: la funzione restituisce None e l'errore compare più avanti (TypeError: unsupported operand type(s) ... NoneType).
  • print al posto di return.
  • Chiamare senza parentesi: f è l'oggetto funzione, f() la chiamata.
  • Default mutabile condiviso tra chiamate.

Teoria collegata