Definire una funzione
Finora abbiamo utilizzato solo le funzioni fornite con Python ma è anche possibile aggiungere nuove funzioni. Una definizione di funzione specifica il nome di una nuova funzione e la sequenza di istruzioni che vengono eseguite quando viene chiamata la funzione. Una volta definita una funzione, possiamo riutilizzarla più volte nel corso del nostro programma, evitando di riscrivere lo stesso codice.
nome = ‘Antonio’
def salutaUtente(nome):
print( 'Benvenuto ' + nome)
salutaUtente(nome)
⇒ Benvenuto Antonio
Come avrai capito, def è una parola chiave che indica una definizione di funzione e il nome della funzione è salutaUtente. Le regole per i nomi delle funzioni sono le stesse dei nomi delle variabili: sono consentite lettere, numeri e alcuni segni di punteggiatura ma il primo carattere non può essere un numero. Non puoi utilizzare una parola chiave come nome di una funzione e dovresti evitare di avere una variabile e una funzione con lo stesso nome.
Le parentesi dopo il nome della funzione servono ad indicare gli argomenti della funzione, se sono vuote indicano che la funzione non accetta alcun argomento. In questo caso la funzione accetta un parametro in ingresso ovvero il nome dell’utente da salutare.
La prima riga della definizione della funzione si chiama intestazione ; il resto si chiama corpo . L’intestazione deve terminare con due punti e il corpo deve essere indentato. Per convenzione, l’indentazione è sempre di quattro spazi. Il corpo può contenere qualsiasi numero di istruzioni infatti se digiti una definizione di funzione in modalità interattiva, l’interprete stampa i puntini di sospensione (…) per informarti che la definizione non è completa. Per terminare la funzione, devi inserire una riga vuota (ciò non è necessario in uno script).
Un aspetto peculiare di Python è che la definizione di una funzione crea una variabile con lo stesso nome e la sintassi per chiamare (o invocare) una funzione da noi creata è la stessa usata per le funzioni incorporate in Python. Dopo aver definito una funzione, è possibile utilizzarla all’interno di un’altra funzione.
nome = ‘Antonio’
def salutaUtente(nome):
print(‘Benvenuto ‘ + nome)
def accessoSicuro(nome):
salutaUtente(nome)
print( ‘Pin inviato’ )
accessoSicuro( nome)
⇒ Benvenuto Antonio
Pin inviato
Le definizioni delle funzioni vengono eseguite esattamente come le altre istruzioni ma l’effetto è quello di creare oggetti funzione. Le istruzioni all’interno della funzione non vengono eseguite finché la funzione non viene chiamata e la definizione della funzione non genera alcun output. Come ci si potrebbe aspettare, è necessario creare una funzione prima di poterla eseguire, in altre parole, la definizione della funzione deve essere eseguita prima della prima chiamata. Al fine di garantire che una funzione sia definita prima del suo primo utilizzo, è necessario conoscere l’ordine in cui vengono eseguite le istruzioni, tale ordine è chiamato flusso di esecuzione . L’esecuzione inizia sempre alla prima istruzione del programma e le dichiarazioni vengono eseguite una alla volta, in ordine dall’alto verso il basso. Le definizioni delle funzioni non alterano il flusso di esecuzione del programma, ma ricordano che le istruzioni all’interno della funzione non vengono eseguite fino a quando non viene chiamata la funzione.
Una chiamata di funzione è come una deviazione nel flusso di esecuzione infatti al posto di passare all’istruzione successiva, il flusso salta al corpo della funzione, esegue tutte le istruzioni presenti nel corpo della funzione e quindi riprende da dove era stato interrotto. Sembra abbastanza semplice, fino a quando non ricordi che una funzione può chiamarne un’altra.
Nel mezzo di una funzione, il programma potrebbe dover eseguire le istruzioni in un’altra funzione creando così un ciclo complesso. Fortunatamente, Python è bravo a tenere traccia di dove si trova, quindi ogni volta che una funzione viene completata, il programma riprende da dove era stato interrotto nella funzione che lo chiamava. Quando raggiunge la fine del programma, il programma termina. Alla luce di ciò, quando leggi un programma, non limitarti a leggerlo dall’alto verso il basso, a volte ha più senso seguire il flusso dell’esecuzione.
Alcune delle funzioni integrate, così come la funzione appena creata richiedono argomenti. Alcune funzioni accettano anche più di un argomento e all’interno della funzione, tali argomenti sono assegnati a variabili chiamate parametri .
I parametri vengono valutati prima che la funzione venga chiamata e bisogna chiarire un aspetto molto importante che può causare confusione, soprattutto per i principianti. Il nome della variabile che passiamo come argomento (nome) non ha nulla a che fare con il nome del parametro (nome). Non importa come è stato denominato il valore nel chiamante; nella funzione il parametro può avere un nome diverso.
Modifichiamo l’esempio per rendere il concetto più chiaro:
nome = ‘Antonio’
def salutaUtente(nome):
print(‘Benvenuto ‘ + nome)
def accessoSicuro(nome_utente):
salutaUtente(nome_utente)
print( ‘Pin inviato’ )
accessoSicuro(nome)
⇒ Benvenuto Antonio
Pin inviato
Come vedi abbiamo definito una variabile nome che passiamo in input alla funzione accessoSicuro(). Il parametro con cui è stata definita accessoSicuro() è nome_utente ma non è fondamentale passare in input una variabile con lo stesso nome.
Perchè dividere un programma in funzioni
Potrebbe non essere chiaro il motivo per cui valga la pena dividere in funzioni.
Esistono, in realtà, diversi motivi:
• La creazione di una nuova funzione offre l’opportunità d’identificare un gruppo di istruzioni, facilitando la lettura, la comprensione e il debug (identificazione di errori) del programma;
• Le funzioni possono ridurre la lunghezza di un programma eliminando il codice ripetuto. Se hai delle funzioni e apporti una modifica, devi solo apportarla in un unico punto;
• Dividere un lungo programma consente di eseguire il debug delle parti una alla volta e quindi assemblarle in un unico insieme funzionante;
• Le funzioni ben progettate sono spesso utili per molti programmi. Dopo averle scritte ed aver eseguito il debug, è possibile riutilizzarle.
Consiglio fortemente l’uso delle funzioni e, nonostante tu possa essere un po’ restio al loro uso, ben presto ti accorgerai di quanto tempo possono farti risparmiare. Assicurati di creare funzioni con un nome adatto al loro compito e, soprattutto, che eseguano solo un compito in modo da essere atomiche e da non incorporare più attività al loro interno.
Nel dettaglio:
Definizione
Il blocco di codice in cui si definisce una funzione ha la seguente struttura:
def nome_funzione(input1,input2): #corpo della funzione: qui si fa qualcosa … … [return valore_restituito (anche nulla oppure più valori)]
In pratica:
Da notare:
il blocco di codice inizia con def
dopo def segue, sulla stessa riga tra parentesi tonde, la lista dei parametri separati da virgole
segue,sulla stessa riga, il carattere :
dopo i due punti segue il corpo della funzione che, in genere, è a un (1) livello di indentazione superiore
la funzione termina con l’istruzione return, seguita eventualmente dai valori restituiti
Terminata la funzione si scende di un livello nell’ indentazione.Esecuzione
definire una funzione non vuol dire eseguirla!!
Passaggio di argomenti a una funzione
Abbiamo visto solo una tipologia di passaggio di argomenti a funzioni.
In realta’ ne esistono 4 (come vedremo l’ordinamento della seguente lista e’ significativo):
I. per posizione
II. per nome
III. per posizione in numero variabile
IV. per nome in numero variabile

1) per posizione

2) per nome
Uso la sintassi nomeparametro = argomento
In questo caso gli argomenti passati per nome possono essere ordinati a piacere:

3) per posizione in numero variabile (*args)
Posso definire una funzione in modo che accetti un numero variabile di argomenti passati per posizione:

La notazione *args e’ uno standard in Python ma l’interprete accetterebbe qualsiasi nome dopo l’asterisco:

Python interpreta il nome che segue l’asterisco come una toupla!
Non posso passare nessun argomento per nome a una funzione come funz3!!!
4) per nome in numero variabile (**kwargs)
Uso il doppio asterisco nella definizione della funzione:

Quindi kwargs (o meglio il nome che segue il doppio asterisco) è un dizionario che contiene come chiavi i nomi dei parametri e come valori il valori del parametro associato.
Nota bene!
Non posso passare alcun argomento per posizione a funz4:

3+4) funzioni che accettano un numero variabile di argomenti per posizione e per nome (*args,**kwargs)
combinando le due ultime opzioni e’ possibile definire funzioni che accettano un numero qualsiasi di argomenti sia per posizione sia per nome.

Parametri di default
I parametri di una funzione, possono anche avere un valore di default, che viene assunto quando non diversamente specificato:

I parametri di default sono valutati nel momento in cui la funzione e’ definita … e non ogni volta che la funzione e’ eseguita.
Cio’ e’ evidente con il seguente esempio:

[elementor-template id=”12586″]
[no_toc]
(203)
Altri articoli nella categoria "Lezioni di Informatica"
- Break-Even Point nel Franchising: Calcolo Avanzato, Automazione e Royalty (con Modelli in Python)
- Regressione lineare: esercizi progressivi dai minimi quadrati alla regressione multipla
- Microeconomia applicata: choke price, domanda esponenziale, segmentazione e prezzo ottimale – Parte 2
- Microeconomia applicata: choke price, prezzo di riserva massimo e prezzo ottimale
- Quanti Centri Ha una Figura Geometrica? Dal Baricentro al Pentagramma
- Microeconomia Computazionale: Come la Domanda di Mercato Emerge dai Comportamenti Individuali
- Legge di Benford e Data Quality nel Marketing: Guida, Formule ed Esercizi Python
- Microeconomia dell’AI: 6 esercizi matematici su costi, pricing, domanda ed elasticità
- Equazioni trascendenti: come risolverle con Python, dal punto fisso a Newton e Brent
- Equazioni Omogenee Esponenziali: Guida Pratica con Esercizi Svolti e Applicazioni

