Skip to content

6. Funzioni

Image

6.1. Script [fonc_01]: ambito delle variabili

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

#  variable scope
def f1():
    #  avoid using global variables
    #  global variable i
    global i
    i += 1
    #  local variable j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")


def f2():
    #  avoid using global variables
    #  global variable i
    global i
    i += 1
    #  local variable j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")


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


#  main program
i = 0
j = 0
#  these two variables will only be known by a function f
#  only if it explicitly declares in the global instruction that it wants to use them
#  or that the function uses the global variable for reading only
f1()
f2()
f3()
#  j hasn't changed but i has
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 illustra l'uso della variabile i, dichiarata come 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] si basa sullo script [fonc_02] e mostra come evitare l'uso delle variabili globali:

#  variable scope
def f1(i):
    #  local variable i
    i += 1
    #  local variable j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")
    #  return the modified value
    return i


def f2(i):
    #  local variable i
    i += 1
    #  local variable j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")
    #  return the modified value
    return i


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


#  main program
i = 0
j = 0
#  these two variables will only be known by a function f
#  only if it explicitly declares in the global instruction that it wants to use them
#  or if the function uses the global variable for reading only
i = f1(i)
i = f2(i)
f3()
#  j hasn't changed but i has
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. Il programma principale 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] illustra una particolarità delle variabili utilizzate sia all'interno di una funzione che nel codice che la chiama, a seconda che la variabile sia utilizzata solo per la lettura all'interno della funzione o meno.

def f1():
    #  here the global variable i is known
    print(f"[f1] i={i}")
    #  here the global variable j is known
    print(f"[f1] j={j}")


def f2():
    #  here the global variable i is not known
    #  because the f2 function defines a local variable with the same name
    #  it then has priority
    try:
        #  try displaying the local variable i defined below
        print(f"[f2] i={i}")
        #  the following instruction makes i a local variable of function f2
        i = 7
    except BaseException as erreur:
        print(f"[f2] erreur={erreur}")


def f3():
    #  here the global variable i is not known
    #  because the f3 function defines a local variable with the same name
    #  it then has priority

    #  the following instruction makes i a local variable
    i = 7
    #  display - here i is known
    print(f"[f3] i={i}")


#  hand -----------
#  global variables to functions
i = 10
j = 20
#  call from f1
f1()
print(f"[main] i={i}, j={j}")
#  call from f2
f2()
print(f"[main] i={i}")
#  call from 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 proveniente dal 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]. Questa funzione quindi “nasconde” la variabile [i] al codice chiamante;
  • riga 14: l'operazione di scrittura sulla variabile locale [i] fallirà perché non ha alcun valore quando si raggiunge la riga 14. Essa ottiene il suo valore alla riga 16. Si verificherà un'eccezione. Per questo motivo, la riga 14 è stata inserita all'interno di un blocco try/catch;
  • righe 21–29: la funzione f3 fa la stessa cosa della funzione f2 ma definisce la sua variabile locale [i] prima;

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:

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


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


#  ------------------------ hand
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": non possono essere modificati. È il caso dei numeri, delle stringhe e delle tuple. Quando gli oggetti Python vengono passati come argomenti alle funzioni, sono i loro riferimenti ad essere passati, a meno che questi oggetti non siano "immutabili", nel qual caso è il valore dell'oggetto ad essere passato;
  • Le funzioni f1 (riga 2) e f2 (riga 7) hanno lo scopo di illustrare il passaggio di un parametro di output. Vogliamo che il parametro effettivo di una funzione venga modificato dalla funzione;
  • Righe 2–3: La funzione f1 modifica il suo parametro formale a. Vogliamo 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 diversi;
  • righe 8–10: la funzione f2 modifica i propri parametri formali a e b e li restituisce come risultati;
  • righe 17–18: i parametri effettivi (x, y) vengono passati a f2 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.

Concludiamo che quando gli oggetti "immutabili" sono parametri di output, devono far parte dei risultati restituiti dalla funzione.

6.5. Script [fonc_05]: Ordine delle funzioni in uno script

Lo script [fonc_05] mostra che una funzione non può essere chiamata se non è stata incontrata in precedenza nel codice:

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

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


#  function 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 delle funzioni in uno script

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

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


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


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

Note

  • riga 3: la funzione [f2] utilizza la funzione [f1] definita più avanti nello script. Tuttavia, ciò non causa un errore. Possiamo quindi concludere che l'ordine in cui le funzioni sono definite 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 le funzioni riutilizzabili in un modulo, anziché spostarle 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:

1
2
3
4
5
6
7
#  function f2
def f2(a, b):
    return f1(a + b)

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

Esistono diversi modi per garantire che le funzioni presenti nello script [fonctions_module_01] possano essere richiamate da altri script. Questi metodi variano a seconda che lo script venga eseguito all'interno di [PyCharm] o meno.

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

Image

  • in [4], la cartella ha cambiato colore;

Dopo questa operazione, la cartella [funzioni/moduli] viene riconosciuta come cartella sorgente. È quindi possibile scrivere in uno script:

from fonctions_module_01 import f2

Per importare/utilizzare la funzione f2 definita nel modulo [functions_module_01.py].

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

  • sopra, la sequenza [1-6] consente di utilizzare la cartella [shared] come cartella in cui memorizzare i moduli da importare;

Per ora, non dichiareremo nessuna cartella come [Sources Root] diversa dalla radice del progetto:

Image

Una volta fatto ciò, possiamo scrivere il seguente script [fonc-07]:

1
2
3
4
5
6
7
8
#  using modules
import sys

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

print(f2(100, 200))
  • Riga 2: importiamo l'oggetto [sys] in modo da poter utilizzare il suo attributo [path] alla riga 5, che fornisce il cosiddetto [Python Path]: un elenco di directory in cui verranno cercati i moduli importati;
  • riga 6: importiamo la funzione f2 dal modulo [fonctions_module_01]. Per fare riferimento a questo modulo, utilizziamo il percorso che va dalla radice del progetto al modulo. Con PyCharm, la radice del progetto è sempre inclusa nelle cartelle cercate quando si cerca un modulo importato in uno script. Questa cartella fa quindi parte del [Python Path] del progetto. Questo è ciò che la riga 5 ci permetterà di verificare;
  • Riga 6: se dovessimo descrivere il percorso dalla radice del progetto alla cartella [fonctions_module_01], scriveremmo [fonctions/shared/fonctions_module_01]. Nel percorso di un modulo, la barra / viene sostituita da un punto. Scriviamo quindi [fonctions.modules.fonctions_module_01];
  • Dopo la riga 6, viene definita la funzione f2. La utilizziamo 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, possiamo vedere che la radice del progetto fa parte del [Python Path];
  • evidenziato in giallo, si può notare che anche la cartella contenente lo script eseguito fa parte del [Python Path];
  • gli altri elementi del [Python Path] provengono direttamente dalla cartella di installazione di Python;

Cosa succede quando non usiamo PyCharm per eseguire [fonc-07]?

Image

Image

  • in [1], eseguiamo lo script [fonc-07]. Ci troviamo nella cartella [functions];
  • In [2], vediamo che la directory di esecuzione fa parte del [Python Path]. È sempre così. Possiamo anche vedere che la directory principale [C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020] non fa parte del [Python Path];
  • in [3], l'interprete Python segnala che non riesce a trovare il modulo [fonctions];

Per trovare il modulo importato [fonctions.shared.fonctions_module_01], l'interprete Python cerca nelle cartelle del [Python Path] una sottocartella denominata [fonctions]. Non riesce a trovarla da nessuna parte. Questo perché la sottocartella [functions] si trova nella cartella [C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020], che non fa parte del [Python Path].

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

6.8. Script [fonc_08]: Aggiunta di cartelle al [Python Path]

È possibile modificare il [Python Path] a livello di programmazione, come mostrato nello script [fonc-08]:

#  using modules
import os
import sys

#  script folder
script_dir = os.path.dirname(os.path.abspath(__file__))
#  Python Path before modification
print(f"Python path avant={sys.path}")
#  add the [shared] folder to the Python Path
sys.path.append(f"{script_dir}/shared")
#  Python Path after modification
print(f"Python path après={sys.path}")

#  import f2
from fonctions_module_01 import f2

#  ------------------------ hand
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 percorso assoluto del file il cui nome le viene passato. La funzione [os.path.dirname] restituisce il percorso assoluto della directory contenente il file il cui nome le viene passato;
  • Riga 10: [sys.path] è una lista contenente i nomi delle directory da cercare quando si cerca un modulo. Aggiungiamo a questa lista la radice del progetto definita alla riga 4;
  • visualizziamo il [Python Path] prima (riga 8) e dopo (riga 12) la modifica;
  • riga 15: importiamo il modulo [fonctions_module_01], che contiene la funzione f2;

L'esecuzione in PyCharm produce 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: vediamo che la cartella [shared] compare due volte nel [Python Path]. Possiamo evitarlo, ma in questo caso non causa alcun problema;
  • riga 4: la funzione f2 è stata eseguita con successo;

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 prima, la cartella [shared] non è nel [Python Path];
  • riga 3: ora lo è;
  • riga 4: la funzione f2 è stata trovata;

6.9. Script [fonc_09]: dichiarazione dei tipi 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 per documentare la funzione. L'interprete Python non verifica se i parametri effettivi della funzione sono del tipo previsto. Tuttavia, PyCharm segnala le incongruenze di tipo tra i parametri effettivi e quelli formali. Questo motivo da solo rende indispensabili le dichiarazioni di tipo.

Lo script è il seguente:

#  a function with parameter type indication
#  this is for documentation purposes only, as the python interpreter ignores it


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


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

Note:

  • Riga 5: dichiariamo che il parametro formale [param] è di tipo [int] e che anche il tipo di ritorno della funzione è [int];
  • riga 11: il parametro effettivo della funzione [show] è del tipo corretto;
  • riga 12: il parametro effettivo della funzione [show] non è del 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] è [str]. Quando appare questo messaggio, abbiamo già inserito il codice della funzione [show]. L'interprete Python ha quindi accettato che il parametro effettivo della funzione [show] sia di tipo [str];
  • La riga 7 del codice genera l'eccezione mostrata nelle righe 4–10 dei risultati;

PyCharm indica comunque che c'è un problema:

Image

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

6.10. Script [fonc_10]: parametri denominati

Per passare parametri a una funzione, è possibile utilizzare i nomi dei suoi parametri formali. In questo caso, non è necessario seguire l'ordine dei parametri formali:

1
2
3
4
5
6
7
#  we can refer to the actual parameters by their formal names
def f(x, y):
    return x + y


#  hand
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 in almeno due casi:
    • la funzione ha molti parametri, la maggior parte dei quali ha valori predefiniti. Quando si chiama la funzione, la tecnica sopra descritta consente di inizializzare solo quei parametri per i quali non si desidera utilizzare il valore predefinito;
    • se i parametri formali hanno nomi significativi, 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 richiama se stessa):

#  recursive function
def fact(i: int) -> int:
    #  factorial(1) is 1
    #  a recursive function must terminate at a certain point
    if i == 1:
        return 1
    else:
        #  factorial(i)=i*factorial(i-1)
        return i * fact(i - 1)


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

Commenti

  • righe 1-9: la funzione fattoriale;
  • riga 9: la funzione [factorial] chiama se stessa;
  • righe 5-6: una funzione ricorsiva deve sempre terminare quando viene soddisfatta 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 ricorsione:

#  recursive function
#  behavior of parameter j


def fact(i: int, j: int) -> int:
    #  stop recursive function
    if i == 1:
        print(f"j={j}")
        return 1
    else:
        #  we manipulate j
        j += 1
        print(f"avant fact j={j}")
        #  recursivity
        f = fact(i - 1, j)
        print(f"après fact j={j}")
        #  result
        return i * f


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

Commenti

  • riga 5: ci stiamo ancora concentrando sulla funzione fattoriale. Aggiungiamo il parametro [j];
  • riga 12: la variabile j viene incrementata regolarmente ad ogni calcolo del fattoriale. Visualizziamo il suo 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: vediamo che il valore di [j] aumenta finché la ricorsione continua, fino a quando non soddisfa la condizione in cui la ricorsione si interrompe. Da quel momento in poi, il ritorno dalle chiamate alla funzione [fact] avviene nell'ordine inverso delle chiamate;
  • righe 10–16: queste visualizzazioni riflettono i successivi ritorni dalla chiamata al fattoriale. La variabile [j] torna al suo valore iniziale di 1;