Sostieni AppuntiFacili con una piccola donazione su PayPal
Dona con PayPalLe funzioni in Python, e in generale in tutti i linguaggi di programmazione, sono sostanzialmente dei blocchi di codice riutilizzabili; possono essere pensate come dei “sottoprogrammi” richiamabili da altri programmi. Grazie alle funzioni è possibile definire dei blocchi di codice che vengono eseguiti unicamente quando vengono richiamati. Le funzioni servono per svolgere molteplici scopi:
Immaginiamo di dover eseguire la stessa operazione di conversione della temperatura da Fahrenheit a Celsius diverse volte nello stesso programma.
Senza le funzioni scriveremmo:
temp1 = 77
celsius1 = (temp1 - 32) * 5 / 9
print(celsius1)
temp2 = 95
celsius2 = (temp2 - 32) * 5 / 9
print(celsius2)
temp3 = 50
celsius3 = (temp3 - 32) * 5 / 9
print(celsius3)
Con le funzioni:
def fahrenheit_to_celsius(fahrenheit):
return (fahrenheit - 32) * 5 / 9
print(fahrenheit_to_celsius(77))
print(fahrenheit_to_celsius(95))
print(fahrenheit_to_celsius(50))
La sintassi di una funzione in in generale è:
def nome_funzione (elenco_parametri):
istruzioni
return valore_restituito
Dove:
INFO
È possibile creare una funzione vuota in python (perchè magari non sappiamo ancora come popolarla) usando la parola chiave: pass
def funzione_vuota():
pass Per chiamare una funzione basta usare il nome della funzione seguita dalle parentesi:
def saluta():
print("Hello World!")
saluta()
Possibile passare dei dati come input alla funzione che si vuole chiamare, a patto che li accetti, inserendoli come argomenti alla chiamata.
def saluta(nome, eta):
print(f"Ciao {nome}, un uccellino mi ha detto che hai {eta} anni")
saluta("Marco", 45)
saluta("Marina", 77)
WARNING
Nell’esempio precedente non sono stati specificati i tipi delle variabili “nome” e “eta”, quindi il chiamante potrebbe passare qualsiasi cosa. Noi sappiamo per logica che nome dovrebbe essere una stringa e eta dovrebbe essere un valore intero, ma non c’è nessun tipo di forzatura sul tipo richiesto.
Quindi il chiamante potrebbe fare una chiamata di questo tipo, senza beccare nessun tipo di errore:
saluta(789, 'd')Il che non avrebbe nessun senso logico.
Per questa ragione è consigliato (ma non obbligatorio) inserire il tipo di valore (type hint) ai valori nella definizione della funzione:
def saluta(nome: str, eta: int):
print(f"Ciao {nome}, un uccellino mi ha detto che hai {eta} anni")
saluta("Marco", 45) # OK
saluta(789, 'd') # ERORRE Spesso i termini parametri e argomenti vengono confusi e inverti, ma è necessario al fine di capirsi, conoscere la distinzione.
Per ora è stato dato per scontato, ma di default se la funzione richiede x numero di parametri, allore il chimante dovrà passarli tutti x nel medesimo ordine.
Come fatto per l’esempio precedente della funzione saluta()
È possibile però assegnare dei valori di default ai parametri della funzione. In questo caso se il chiamante non fornirà tali argomenti, la funzione assegnerà i valori di default.
def saluta(nome: str, eta: int = 18):
print(f"Ciao {nome}, un uccellino mi ha detto che hai {eta} anni")
saluta("Marco", 45) # OUTPUT: Ciao Marco, un uccellino mi ha detto che hai 45 anni
saluta("Anna") # OUTPUT: Ciao Anna, un uccellino mi ha detto che hai 18 anni
È possibile anche chiamare una funzione specificando esplicitamente il nome dei parametri, indipendentemente dall’ordine.
def saluta(nome: str, eta: int):
print(f"Ciao {nome}, hai {eta} anni")
saluta(eta=30, nome="Luca")
Questo rende il codice:
In python è possibile forzare alcuni parametri ad essere solo posizionali, usando il simbolo /:
def somma(a, b, /):
return a + b
somma(3, 4) # OK
somma(a=3, b=4) # ERRORE
Tutti i parametri prima di / devono essere passati per posizione.
Al contrario, possiamo forzare alcuni parametri ad essere passati solo per chiave, usando *.
def login(*, username, password):
print(f"Login di {username}")
login(username="admin", password="1234") # OK
login("admin", "1234") # ERRORE
Tutti i parametri dopo * devono essere specificati con il loro nome.
Quando non sappiamo quanti argomenti verranno passati a una funzione, possiamo usare:
def somma(*args):
totale = 0
for numero in args:
totale += numero
return totale
print(somma(1, 2, 3))
print(somma(5, 10, 15, 20))
def stampa_dati(**kwargs):
for chiave, valore in kwargs.items():
print(f"{chiave}: {valore}")
stampa_dati(nome="Anna", eta=25, citta="Roma")
Lo scope definisce dove una variabile è accessibile.
In genere è sempre preferibile avere variabili locali per avere maggiore controllo delle variabili.
Le variabili definite dentro una funzione sono locali:
def funzione():
x = 10
print(x)
funzione()
# print(x) → ERRORE
Le variabili definite fuori dalle funzioni sono globali:
x = 5
def funzione():
print(x)
funzione()
INFO
Per modificare una variabile globale dentro una funzione bisogna usare global:
x = 5
def cambia():
global x
x = 10
cambia()
print(x) # 10 I decoratori sono funzioni che modificano il comportamento di altre funzioni.
def mio_decoratore(funzione):
def wrapper():
print("Prima della funzione")
funzione()
print("Dopo la funzione")
return wrapper
@mio_decoratore
def saluta():
print("Ciao!")
saluta()
Output:
Prima della funzione
Ciao!
Dopo la funzione
Le lambda sono funzioni anonime, scritte in una sola riga.
somma = lambda a, b: a + b
print(somma(3, 4))
Sono utili per:
map(), filter(), sorted()Esempio:
numeri = [1, 2, 3, 4]
quadrati = list(map(lambda x: x**2, numeri))
Una funzione è ricorsiva quando chiama sé stessa.
Esempio: fattoriale
def fattoriale(n):
if n == 0:
return 1
return n * fattoriale(n - 1)
print(fattoriale(5)) # 120
Ogni funzione ricorsiva deve avere:
return 1 nell’esempio sopra)return n * fattoriale(n - 1) nell’esempio sopra)I generatori permettono di produrre valori uno alla volta usando yield.
def contatore(n):
for i in range(n):
yield i
for numero in contatore(5):
print(numero)
Vantaggi:
1) A cosa serve una funzione?
2) Cosa restituisce una funzione senza return?
3) Cosa rappresenta *args?
4) Qual è lo scopo di yield?
5) Una funzione ricorsiva deve avere:
Scrivi una funzione che calcoli il quadrato di un numero.
Scrivi una funzione che accetti un numero variabile di argomenti e ne calcoli la media.
Crea una funzione ricorsiva che calcoli la somma dei numeri da 1 a n.
Scrivi un generatore che produca i numeri pari fino a un valore dato.
Scrivi una funzione chiamata “analizza_lista” che:
Esempio:
numeri = [3, 7, 2, 9, 4]
risultato = analizza_lista(numeri)
print(risultato)
Output atteso: (25, 5.0, 9, 2)
Scrivi una funzione chiamata “statistiche_studenti” che:
riceva un dizionario nel formato:
studenti = {
"Anna": 28,
"Marco": 22,
"Luca": 30,
"Sara": 25
}
restituisca:
Output di esempio: (“Luca”, “Marco”, 26.25)
Scrivi una funzione “crea_profilo” che:
**kwargsEsempio:
profilo = crea_profilo(
"Anna",
"Rossi",
eta=25,
citta="Roma",
hobby="pittura"
)
print(profilo)
Realizza il gioco del Tris usando le funzioni.
Requisiti minimi:
stampa_griglia(griglia) che mostri il campo di giocomossa(griglia, posizione, simbolo) che:
X o O)controlla_vittoria(griglia, simbolo) che ritorni True se il giocatore ha vintoEsempio di griglia:
X | O | X
---------
O | X |
---------
| O | X
Prenota una lezione