Funzioni nidifcate

s
sam_dc (680 points)
3 6 7
asked Nov 3, 2019 in Programmare in Python by sam_dc (680 points)
edited Nov 3, 2019 by sam_dc

Mi accorgo che la domanda può sembrare banale, ma avrei bisogno di fare chiarezza sull'utilizzo delle funzioni nidificate.
Non mi è ben chiaro come far lavorare tra loro le funzioni che definisco singolarmente.
Credo di fare errori nell'utilizzo di 'return'.

Nel seguente esempio vorrei passare i parametri L1 ed L2 alla funzione es(), per far si che venga creata una struttura dati a partire dall'input L2, sulla quale vengono fatte delle operazioni utilizzando le informazioni presenti in L1 ed L2.
Infine la funzione calcola_risultato (a partire dalla struttura dati sulla quale sono state fatte le operazioni) seleziona i valori da aggiungere alla lista vuota (risultato = [] ).
Vorrei ottenere come output la lista 'risultato'.

Da quello che ho capito:

def es(L1, L2):
     def crea_struttura_dati(L2):                               # viene creata la struttura dati da passare alle seguenti funzioni

          return struttura_dati                                        # lo inserisco qui ?

                 def operazioni_1(L1, struttura dati):        # le due funzioni hanno lo stesso livello di indentazione
                        #istruzioni

                         return struttura_dati_modificata       # lo inserisco qui ?

                 def operazioni_2(L2, struttura dati):
                         #istruzioni

                         return struttura_dati_modificata       # lo inserisco qui ?

                        def calcola_risultato(struttura_dati_modificata):

                               risultato = []

                               #istruzioni

                               return risultato                             # lo inserisco qui ?    

                        return struttura_dati_modificata         # lo inserisco qui ? 

                        

Dove sbaglio? Devo inserire un return in ogni singola funzione? Devo metterli tutti alla fine indentati con le rispettive funzioni? 

Grazie in anticipo!

    

386 views

4 Answers

AlessandraIzzo (6010 points)
6 6 30
answered Nov 3, 2019 by AlessandraIzzo (6,010 points)
edited Nov 3, 2019 by AlessandraIzzo
Mi sembra che laddove vuoi usare una funzione, la definisci. Le definizioni delle funzioni normalmente le metti tutte sullo stesso livello:

def funz1(...):   # nelle parentesi dichiari i parametri che la funzione accetta
    ....                # corpo della funzione

def funz2(...):
    ....

e poi devi chiamare (questo è il termine che si usa) queste funzioni dove ti servono:

def esempio(...):
    ....
    funz1(...)    # nelle parentesi passi i parametri
    ....
    funz2(...)
s
sam_dc (680 points)
3 6 7
commented Nov 3, 2019 by sam_dc (680 points)
Quindi le funzioni vanno definite tutte allo stesso livello anche se utilizzo variabili locali nelle funzioni in cui queste non sono state definite ?
AlessandraIzzo (6010 points)
6 6 30
commented Nov 3, 2019 by AlessandraIzzo (6,010 points)
Sì, puoi passarle come parametro. Se ho capito male o hai qualche problema, dimmi pure dove l'hai incontrato
T
Trasciatti (1400 points)
10 20 34
commented Nov 4, 2019 by Trasciatti (1,400 points)
Se vuoi che usino una variabile non dichiarata nella funzione, puoi mettere la funzione nella funzione nella quale la dichiari (diciamo come hai fatto tu), oppure puoi metterla nel livello fuori e passargliela come parametro. Non è preferibile una cosa o l'altra, vedi come ti trovi comodo
E
Edward (25950 points)
2 4 172
answered Nov 3, 2019 by Edward (25,950 points)

Se hai delle funzioni una dentro l'altra, ognuna di quelle funzioni avrà un suo return.

Quindi se tu fai return risultato, dentro def risultato, la funzione ritornerà risultato. Però la funzione def es(L1, L2), se non diversamente specificato, non ritorna risultato (dovrebbe avere un return a sua volta).

Nel tuo esempio hai molte funzioni annidate, ma la regola generale è che se vuoi che la funzione es restituisca la variabile risultato, della funzione risultato (calcola che ti consiglio di evitare di dare lo stesso nome a variabili e funzioni perchè non si capisce niente), allora la funzione es deve chiamare la funzione risultato. Solo che la funzione risultato è definita nella funzione crea_struttura_dati(L2), quindi è questa funzione che deve restituire quello che restituisce risultato, ed è questa che devi chiamare dentro la funzione es. L'alternativa siccome sono funzioni annidate è modificare direttamente un oggetto creato da es(L1, L2) e non restituire nulla.

Calcola che uno dei vantaggi dell'avere le funzioni annidate, è che queste possono accedere alle variabili delle funzioni nella quale vengono definite (quindi senza l'uso di parametri). Siccome tu passi comunque i parametri, io ti consiglio di definirle al livello più esterno (in modo da ridurre l'intricatezza). Per esempio se crea_struttura_dati(L2) fosse al livello esterno, tu potresti fare dentro la funzione es una cosa del genere:
struttura_dati = crea_struttura_dati(L2)   (ovviamente alla fine di crea_struttura_dati devi avere un return che la restituisce)
#istruzioni
return struttura_dati_modificata

Non so se sono stato chiaro, ma il tuo esempio ha molte funzioni annidate quindi è difficile spiegarsi.

a
a.pietroluongo (11250 points)
15 38 131
answered Nov 3, 2019 by a.pietroluongo (11,250 points)
Ma per homework non conviene spezzarla in più funzioni?
J
Jan Rogala (7260 points)
3 4 37
commented Nov 3, 2019 by Jan Rogala (7,260 points)
Quello giusto per diminuire la complessità ciclomatica, e poi nel caso il codice viene un po piu "pulito", quindi è sempre consigliabile spezzare l'hw in piu funzioni
fc-dev (16450 points)
12 20 34
commented Nov 3, 2019 by fc-dev (16,450 points)
Dipende.
La chiamata di una funzione aggiunge un leggero overhead, ma allo stesso tempo spezzare il codice in più funzioni riduce la complessità ciclomatica massima, quindi è un po' una questione di prove: fare troppe chiamate a funzioni potrebbe rallentare notevolmente il tuo programma, non farne nessuna invece ti porta ad avere una complessità parecchio alta.
Sta a te trovare la via di mezzo.
andrea.sterbini (172780 points)
513 935 1789
answered Nov 3, 2019 by andrea.sterbini (172,780 points)
1) non usare lo stesso nome x una variabile e x una funzione
2) ogni funzione per tornare il risultato a chi la chiama usa l'istruzione return
3) per ottenere che una funzione esegua un calcolo bisogna chiamarla fornendole i dati da elaborare come argomenti
4) una funzione definita dentro una funzione può leggere gli argomenti e le variabili locali della/e funzione/i che la contengono