Skip to content

6. Le funzioni

Image

6.1. Script [fonc_01]: ambito delle variabili

Lo script [fonc_01] mostra alcuni esempi di ambito delle variabili tra le funzioni:


# ambito delle variabili
def f1():
    # È consigliabile evitare l'uso di variabili globali
    # variabile globale i
    global i
    i += 1
    # variabile locale j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")


def f2():
    # È consigliabile evitare l'uso di variabili globali
    # variabile globale i
    global i
    i += 1
    # variabile locale j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")


def f3():
    # variabile locale i
    i = 1
    # variabile locale j
    j = 30
    print(f"f3[i,j]=[{i},{j}]")


# programma principale
i = 0
j = 0
# queste due variabili saranno note a una funzione f
# solo se questa dichiara esplicitamente, tramite l'istruzione global, di volerle utilizzare
# oppure se la funzione utilizza la variabile globale solo in lettura
f1()
f2()
f3()
# j non è cambiato, ma i è cambiato
print(f"[i,j]=[{i},{j}]")

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_01.py
f1[i,j]=[1,10]
f2[i,j]=[2,20]
f3[i,j]=[1,30]
[i,j]=[2,0]

Process finished with exit code 0

Note:

  • lo script mostra l'utilizzo della variabile i, dichiarata globale nelle funzioni f1 e f2. In questo caso, il programma principale e le funzioni f1 e f2 condividono la stessa variabile i.

6.2. Script [fonc_02]: ambito delle variabili

Lo script [fonc_03] riprende lo script [fonc_02] e mostra come evitare l'uso di variabili globali:


# ambito delle variabili
def f1(i):
    # variabile locale i
    i += 1
    # variabile locale j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")
    # si restituisce il valore modificato
    return i


def f2(i):
    # variabile locale i
    i += 1
    # variabile locale j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")
    # si restituisce il valore modificato
    return i


def f3():
    # variabile locale i
    i = 1
    # variabile locale j
    j = 30
    print(f"f3[i,j]=[{i},{j}]")


# programma principale
i = 0
j = 0
# queste due variabili saranno note a una funzione f
# solo se questa dichiara esplicitamente, tramite l'istruzione global, di volerle utilizzare
# oppure se la funzione utilizza la variabile globale solo in lettura
i = f1(i)
i = f2(i)
f3()
# j non è cambiato, ma i è cambiato
print(f"[i,j]=[{i},{j}]")

Commenti:

  • righe 2, 12: invece di essere dichiarata globale, la variabile [i] viene passata come parametro alle funzioni f1 e f2;
  • righe 9, 19: le funzioni f1 e f2 restituiscono la variabile [i] modificata al programma principale. Quest’ultimo la recupera alle righe 36 e 37;

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_02.py
f1[i,j]=[1,10]
f2[i,j]=[2,20]
f3[i,j]=[1,30]
[i,j]=[2,0]

Process finished with exit code 0

6.3. Script [fonc_03]: ambito delle variabili

Lo script [fonc_03] mostra una particolarità delle variabili utilizzate sia all’interno di una funzione che nel codice che la chiama, a seconda che nella funzione tale variabile sia utilizzata esclusivamente in lettura o meno.


def f1():
    # qui la variabile globale i è nota
    print(f"[f1] i={i}")
    # qui la variabile globale j è nota
    print(f"[f1] j={j}")


def f2():
    # qui la variabile globale i non è nota
    # poiché la funzione f2 definisce una variabile locale con lo stesso nome
    # è quindi questa ad avere la priorità
    try:
        # tentativo di visualizzare la variabile locale i definita più avanti
        print(f"[f2] i={i}")
        # l'istruzione seguente rende i una variabile locale della funzione f2
        i = 7
    except BaseException as erreur:
        print(f"[f2] erreur={erreur}")


def f3():
    # qui la variabile globale i non è conosciuta
    # poiché la funzione f3 definisce una variabile locale con lo stesso nome
    # ed è quindi questa ad avere la priorità

    # l'istruzione seguente definisce i come variabile locale
    i = 7
    # visualizzazione - qui i è nota
    print(f"[f3] i={i}")


# main -----------
# variabili globali alle funzioni
i = 10
j = 20
# chiamata di f1
f1()
print(f"[main] i={i}, j={j}")
# chiamata di f2
f2()
print(f"[main] i={i}")
# chiamata di f3
f3()
print(f"[main] i={i}")

Note

  • riga 34: il codice principale definisce una variabile [i];
  • righe 1-5: anche la funzione f1 utilizza una variabile [i] senza assegnarle alcun valore. Si tratta di una lettura della variabile [i]. In questo caso, la variabile [i] utilizzata è quella del codice chiamante, riga 34;
  • righe 8-18: anche la funzione f2 utilizza una variabile [i], ma le assegna un valore alla riga 16. L'assegnazione di un valore alla variabile [i] in f2 rende automaticamente [i] una variabile locale della funzione [f2]. Quest’ultima “nasconde” quindi la variabile [i] del codice chiamante;
  • riga 14: l'operazione di scrittura della variabile locale [i] fallirà poiché questa non ha alcun valore quando si arriva alla riga 14. Essa ottiene il suo valore alla riga 16. Si verificherà un'eccezione. Per questo motivo, la riga 14 è stata inserita in un try / catch;
  • righe 21-29: la funzione f3 fa la stessa cosa della funzione f2, ma definisce prima la sua variabile locale [i];

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_03.py
[f1] i=10
[f1] j=20
[main] i=10, j=20
[f2] erreur=local variable 'i' referenced before assignment
[main] i=10
[f3] i=7
[main] i=10

Process finished with exit code 0

6.4. Script [fonc_04]: modalità di passaggio dei parametri

Lo script è il seguente:


# funzione f1
def f1(a):
    a = 2


# funzione f2
def f2(a, b):
    a = 2
    b = 3
    return a, b


# ------------------------ main
x = 1
f1(x)
print(f"x={x}")
(x, y) = (-1, -1)
(x, y) = f2(x, y)
print(f"x={x}, y={y}")

Risultati

1
2
3
4
5
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_04.py
x=1
x=2, y=3

Process finished with exit code 0

Note:

  • in Python tutto è un oggetto. Alcuni oggetti sono detti "immutabili" (in inglese): non è possibile modificarli. È il caso dei numeri, delle stringhe di caratteri e delle tuple. Quando gli oggetti Python vengono passati come parametri alle funzioni, vengono passati i loro riferimenti, a meno che tali oggetti non siano "immutabili"; in tal caso, viene passato il valore dell'oggetto;
  • le funzioni f1 (riga 2) e f2 (riga 7) intendono illustrare il passaggio di un parametro di output. Si vuole che il parametro effettivo di una funzione venga modificato dalla funzione stessa;
  • righe 2-3: la funzione f1 modifica il proprio parametro formale a. Si vuole sapere se anche il parametro effettivo verrà modificato;
  • righe 14-15: il parametro effettivo è x=1. La riga 2 dei risultati mostra che il parametro effettivo non viene modificato. Pertanto, il parametro effettivo x e il parametro formale a sono due oggetti distinti;
  • righe 8-10: la funzione f2 modifica i propri parametri formali a e b e li restituisce come risultati;
  • righe 17-18: si passano a f2 i parametri effettivi (x,y) e il risultato di f2 viene assegnato a (x,y). La riga 3 dei risultati mostra che i parametri effettivi (x,y) sono stati modificati.

Se ne deduce che, quando oggetti "immutabili" fungono da parametri di uscita, questi devono far parte dei risultati restituiti dalla funzione.

6.5. Script [fonc_05]: ordine di scrittura delle funzioni in uno script

Lo script [fonc_05] mostra che non è possibile chiamare una funzione se questa non è stata precedentemente incontrata nel codice:


# ------------------------ main
print(f2(100, 200))

# funzione f1
def f1(a):
    return a + 10


# funzione f2
def f2(a, b):
    return f1(a + b)

Note

  • la riga 2 causerà un errore perché utilizza la funzione f2 che non è stata ancora definita nello script;

Risultati

1
2
3
4
5
6
7
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_05.py
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_05.py", line 2, in <module>
    print(f2(100, 200))
NameError: name 'f2' is not defined

Process finished with exit code 1

6.6. Script [fonc_06]: ordine di scrittura delle funzioni in uno script

Lo script [fonc_06] mostra che ciò che vale per il codice chiamante non vale per le funzioni:


# funzione f2
def f2(a, b):
    return f1(a + b)


# funzione f1
def f1(a):
    return a + 10


# ------------------------ main
print(f2(100, 200))

Note

  • riga 3: la funzione [f2] utilizza la funzione [f1] definita più avanti nello script. Ciò non provoca tuttavia alcun errore. Si può quindi concludere che l'ordine di definizione delle funzioni in uno script Python non ha importanza;

Risultati

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_06.py
310

Process finished with exit code 0

6.7. Script [fonc_07]: utilizzo dei moduli

Lo script [fonc_07] mostra come isolare le funzioni in un modulo.

Image

Isoliamo in un modulo le funzioni riutilizzabili. Anziché trasferirle da uno script all'altro:

  • le inseriamo in un file separato che dichiariamo in modo specifico;
  • gli script che necessitano di queste funzioni «importano» il modulo che le contiene;

Lo script [fonctions_module_01] è il seguente:


# funzione f2
def f2(a, b):
    return f1(a + b)

# funzione f1
def f1(a):
    return a + 10

Affinché le funzioni dello script [fonctions_module_01] possano essere richiamate da altri script, esistono diversi modi per procedere. Questi differiscono a seconda che lo script venga eseguito o meno all’interno di [PyCharm].

In [PyCharm] i moduli importati vengono cercati in cartelle specifiche denominate [Sources Root]. Esistono due modi per trasformare una cartella in un [Sources Root]:

Image

  • in [4], la cartella cambia colore;

Dopo questa operazione, la cartella [fonctions/modules] viene riconosciuta come cartella di origine. È quindi possibile scrivere in uno script:

from fonctions_module_01 import f2

per importare/utilizzare la funzione f2 definita nel modulo [fonctions_module_01.py].

Un altro metodo consiste nell’utilizzare le proprietà del progetto:

  • nella sequenza sopra riportata, [1-6] consente di trasformare la cartella [shared] in una cartella in cui archiviare i moduli da importare;

Per il momento non dichiareremo alcuna cartella come [Sources Root], ad eccezione della radice del progetto:

Image

Fatto ciò, possiamo scrivere il seguente script [fonc-07]:


# utilizzo dei moduli
import sys

# ------------------------ main
print(f"Python path={sys.path}")
from fonctions.shared.fonctions_module_01 import f2

print(f2(100, 200))
  • riga 2: si importa l'oggetto [sys] per poter utilizzare, alla riga 5, il suo attributo [path] che fornisce quello che viene chiamato [Python Path]: un elenco di cartelle che verranno esplorate alla ricerca di moduli importati;
  • riga 6: si importa la funzione f2 dal modulo [fonctions_module_01]. Per indicare questo modulo, si utilizza il percorso che porta dalla radice del progetto al modulo. Con PyCharm, la radice del progetto fa sempre parte delle cartelle esplorate quando si cerca un modulo importato in uno script. Questa cartella fa quindi parte del [Python Path] del progetto. È proprio questo che la riga 5 ci permetterà di verificare;
  • riga 6: se dovessimo descrivere il percorso che porta dalla radice del progetto alla cartella [fonctions_module_01], scriveremmo [fonctions/shared/fonctions_module_01]. Nel percorso di un modulo, il segno / viene sostituito dal punto. Si scrive quindi [fonctions.modules.fonctions_module_01];
  • dopo la riga 6, la funzione f2 è nota. La si utilizza alla riga 8;

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_07.py
Python path=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
310

Process finished with exit code 0

Sopra:

  • evidenziato in verde, si vede che la radice del progetto fa parte di [Python Path];
  • evidenziato in giallo, si vede che anche la cartella dello script eseguito fa parte di [Python Path];
  • gli altri elementi del [Python Path] provengono direttamente dalla cartella di installazione di Python;

Cosa succede se non si utilizza PyCharm per eseguire [fonc-07]?

Image

Image

  • in [1], si esegue lo script [fonc-07]. Ci si trova nella cartella [fonctions];
  • in [2], si vede che la cartella di esecuzione fa parte di [Python Path]. È sempre così. Si può anche notare che la cartella radice [C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020] non fa parte di [Python Path];
  • in [3], l’interprete Python segnala di non trovare il modulo [fonctions];

Per cercare il modulo importato [fonctions.shared.fonctions_module_01], l’interprete Python cerca nelle cartelle di [Python Path] una sottocartella denominata [fonctions]. Non lo trova da nessuna parte. Infatti, la sottocartella [fonctions] si trova all’interno della cartella [C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020], che non fa parte di [Python Path].

Lo script [fonc-08] offre una possibile soluzione a questo problema.

6.8. Script [fonc_08]: aggiungere cartelle a [Python Path]

È possibile modificare il file [Python Path] tramite programmazione, come illustrato dallo script [fonc-08]:


# utilizzo dei moduli
import os
import sys

# cartella dello script
script_dir = os.path.dirname(os.path.abspath(__file__))
# Python Path prima della modifica
print(f"Python path avant={sys.path}")
# si aggiunge la cartella [shared] al Python Path
sys.path.append(f"{script_dir}/shared")
# Python Path dopo la modifica
print(f"Python path après={sys.path}")

# import f2
from fonctions_module_01 import f2

# ------------------------ main
print(f2(100, 200))

Note

  • riga 4: la variabile speciale [__file__] è il nome dello script in esecuzione. A seconda del contesto di esecuzione, questo nome può essere assoluto (Pycharm) o relativo (console). La funzione [os.path.abspath] restituisce il nome assoluto del file il cui nome le viene passato. La funzione [os.path.dirname] restituisce il nome assoluto della cartella contenente il file il cui nome le viene passato;
  • riga 10: [sys.path] è un array contenente i nomi delle cartelle da esplorare quando viene cercato un modulo. A questo array viene aggiunta la radice del progetto definita alla riga 4;
  • si visualizza [Python Path] prima (riga 8) e dopo (riga 12) la modifica;
  • riga 15: si importa il modulo [fonctions_module_01] che contiene la funzione f2;

L'esecuzione in PyCharm fornisce i seguenti risultati:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_08.py
Python path avant=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
Python path après=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions/shared']
310

Process finished with exit code 0
  • riga 3: si nota che la cartella [shared] è presente due volte nella cartella [Python Path]. È possibile evitare questa situazione, ma in questo caso non crea problemi;
  • riga 4: la funzione f2 è stata eseguita correttamente;

Ora eseguiamo [fonc-08] in un terminale:


(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions>python fonc_08.py
Python path avant=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
Python path après=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions/shared']
310
  • riga 2: come in precedenza, la cartella [shared] non è presente in [Python Path];
  • riga 3: ora c'è;
  • riga 4: la funzione f2 è stata trovata;

6.9. Script [fonc_09]: dichiarazione del tipo dei parametri

Lo script [fonc_09] mostra che è possibile dichiarare il tipo dei parametri di una funzione così come quello del risultato. Tuttavia, questa dichiarazione è utile solo ai fini della documentazione della funzione. L’interprete Python non verifica che i parametri effettivi della funzione abbiano effettivamente il tipo previsto. Tuttavia, PyCharm segnala le incongruenze di tipo tra parametri effettivi e formali. Questo motivo è già sufficiente a rendere indispensabili le dichiarazioni di tipo.

Lo script è il seguente:


# una funzione con indicazione del tipo dei parametri
# questo serve solo a scopo di documentazione, poiché l'interprete Python non ne tiene conto


def show(param: int) -> int:
    print(f"param={param}, type(param)={type(param)}")
    return param + 1


# main -------------------------
print(show(4))
show("xyz")

Note:

  • riga 5: si dichiara che il parametro formale [param] è di tipo [int] e che anche il risultato della funzione è di tipo [int];
  • riga 11: il parametro effettivo della funzione [show] ha il tipo corretto;
  • riga 12: il parametro effettivo della funzione [show] non ha il tipo corretto;

Risultati

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py
param=4, type(param)=<class 'int'>
5
param=xyz, type(param)=<class 'str'>
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py", line 11, in <module>
    show("xyz")
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py", line 6, in show
    return param + 1
TypeError: can only concatenate str (not "int") to str

Process finished with exit code 1
  • riga 10: il tipo del parametro [param] è di tipo [str]. Quando viene visualizzato questo messaggio, si è già entrati nel codice della funzione [show]. L'interprete Python ha quindi accettato che il parametro effettivo della funzione [show] fosse di tipo [str];
  • la riga 7 del codice genera l’eccezione riportata nelle righe 4-10 dei risultati;

PyCharm indica tuttavia la presenza di un'anomalia:

Image

In [1], PyCharm ha evidenziato la chiamata errata.

6.10. Script [fonc_10]: parametri con nome

Per passare dei parametri a una funzione, è possibile utilizzare i nomi dei parametri formali della stessa. In questo caso, non è necessario rispettare l’ordine dei parametri formali:


# è possibile indicare i parametri effettivi con i loro nomi formali
def f(x, y):
    return x + y


# main
print(f(y=10, x=3))

Note

  • riga 2: la funzione f ha due parametri formali x e y;
  • riga 7: quando si chiama la funzione f, è possibile utilizzare i nomi dei parametri formali. Questa pratica può essere utile almeno in due casi:
    • la funzione ha molti parametri, la maggior parte dei quali ha un valore predefinito. Al momento della chiamata, la tecnica precedente consente di inizializzare solo i parametri per i quali non si desidera utilizzare il valore predefinito;
    • se i parametri formali hanno un nome significativo, l'uso di parametri con nome nella chiamata alla funzione migliora la leggibilità del codice;

Risultati

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_10.py
13

Process finished with exit code 0

6.11. Script [fonc_11]: funzione ricorsiva

Lo script [fonc_11] è un esempio di funzione ricorsiva (che chiama se stessa):


# funzione ricorsiva
def fact(i: int) -> int:
    # fattoriale(1) è 1
    # una funzione ricorsiva deve terminare a un certo punto
    if i == 1:
        return 1
    else:
        # fattoriale(i) = i * fattoriale(i-1)
        return i * fact(i - 1)


# ---------- main
print(f"fact(8)={fact(8)}")

Commenti

  • righe 1-9: la funzione fattoriale;
  • riga 9: la funzione [factorielle] si richiama a se stessa;
  • righe 5-6: una funzione ricorsiva deve sempre terminare quando si verifica una condizione, altrimenti si ha una ricorsione infinita;

Risultati

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_11.py
fact(8)=40320

Process finished with exit code 0

6.12. Script [fonc_12]: funzione ricorsiva

La funzione [fonc_12] fornisce ulteriori dettagli sul funzionamento della ricorsività:


# funzione ricorsiva
# comportamento del parametro j


def fact(i: int, j: int) -> int:
    # interruzione della funzione ricorsiva
    if i == 1:
        print(f"j={j}")
        return 1
    else:
        # si manipola j
        j += 1
        print(f"avant fact j={j}")
        # ricorsività
        f = fact(i - 1, j)
        print(f"après fact j={j}")
        # risultato
        return i * f


# ---------- main
print(f"fact(8)={fact(8, 0)}")

Commenti

  • riga 5: ci si concentra ancora sulla funzione fattoriale. Le viene aggiunto il parametro [j];
  • riga 12: la variabile j viene incrementata regolarmente ad ogni fattoriale. Ne viene visualizzato il valore prima (riga 12) e dopo (riga 16) la ricorsione (riga 15);

Risultati

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_12.py
avant fact j=1
avant fact j=2
avant fact j=3
avant fact j=4
avant fact j=5
avant fact j=6
avant fact j=7
j=7
après fact j=7
après fact j=6
après fact j=5
après fact j=4
après fact j=3
après fact j=2
après fact j=1
fact(8)=40320

Process finished with exit code 0
  • righe 2-8: si osserva che il valore di [j] cresce finché la ricorsione continua, fino a quando non si verifica la condizione che la interrompe. Da quel momento in poi, il ritorno dalle chiamate alla funzione [fact] avviene in ordine inverso rispetto alle chiamate;
  • righe 10-16: queste visualizzazioni riflettono i successivi ritorni della chiamata al fattoriale. La variabile [j] torna ai suoi valori precedenti fino a raggiungere il valore iniziale 1;