3.3. Les fonctions def#

Evidemment, même si la fonction peut s’écrire sur une seule ligne, il est possible d’utiliser def plutôt qu’une lambda-fonction. Nous reprenons donc les exemples précédents avec cette nouvelle syntaxe.

Important

  • A nouveau l’indentation est synthaxique donc obligatoire.

  • La fonction peut prendre autant d’arguments que nécessaire (cela peut être 0 ou bien n’importe quel entier aussi grand que voulu - il n’y a plus de limites depuis python 3.6).

  • Le mot-clef return permet d’indiquer le (les) résultat(s) que renvoie la fonction. Elle s’arrête aussitôt après, même s’il reste des instructions. La fonction peut n’avoir aucun return, c’est-à-dire ne renvoyer aucune valeur : on peut dans ce cas l’appeler procédure.

def carre(x):
    return x**2
x = 2
print(f"Evaluation de la fonction carre sur x={x} : {carre(x)}")
Evaluation de la fonction carre sur x=2 : 4
def echange(x, y):
    return y, x
x, y = 1, 2
z, t = echange(x, y)
print(f"On échange {x} et {y} : {z}, {t}")
On échange 1 et 2 : 2, 1
def inverse(x):
    if x == 0:
        return None
    return 1./x
x, y = 2, 0
print(f"1/{x} = {inverse(x)}")
print(f"1/{y} = {inverse(y)}")
1/2 = 0.5
1/0 = None

Notez dans le dernier exemple ci-dessous qu’il y a deux return. Si le test x == 0 est vrai alors le premier return est utilisé : la fonction retourne None et s’arrête. Si le test est faux alors la fonction descend au deuxième return.

Il est également possible d’utiliser les fonctions de manière récursive. Par exemple pour calculer \(n!\).

def factorielle(n):
    if n != int(n):
        print(f"{n} n'est pas un entier !")
        return
    if n <= 0:
        print(f"{n} est négatif !")
        return
    if n == 1:
        return 1
    return n * factorielle(n-1)

print(factorielle(17.1))
print(factorielle(-3))
print(factorielle(3))
print(factorielle(100))
17.1 n'est pas un entier !
None
-3 est négatif !
None
6
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Exercice

Proposez une fonction récursive mon_pgcd qui calcule le pgcd de 2 entiers à l’aide de l’algorithme d’Euclide :

  • si \(b = 0, PGCD(a, b) = \vert a \vert\),

  • si \(b \neq 0\), \(PGCD(a, b) = PGCD(b, r)\), où \(r\) est le reste de la division euclidienne de \(a\) par \(b\).

Solution récursive

Hide code cell source
def mon_pgcd(a, b):
    if type(a) != int or type(b) != int:
        print(f"Dans mon_pgcd a={a} et b={b} doivent être entiers")
        return
    if b == 0:
        return abs(a)
    return mon_pgcd(b, a % b)

a, b = 153*17, 153*15
print(f"Le PGCD de {a} et de {b} vaut {mon_pgcd(a, b)}")
Le PGCD de 2601 et de 2295 vaut 153

Solution itérative

Hide code cell source
def mon_pgcd(a, b):
    if type(a) != int or type(b) != int:
        print(f"Dans mon_pgcd a={a} et b={b} doivent être entiers")
        return
    while b != 0:
        a, b = b, a % b
    return abs(a)

a, b = 153*17, 153*15
print(f"Le PGCD de {a} et de {b} vaut {mon_pgcd(a, b)}")
Le PGCD de 2601 et de 2295 vaut 153