Une introduction à Python 3

Image non disponible


précédentsommairesuivant

5. Fonctions et espaces de noms

Image non disponible

Les fonctions sont les éléments structurants de base de tout langage procédural.

Elles offrent différents avantages :

  • évitent la répétition : on peut « factoriser » une portion de code qui se répète lors de l'exécution en séquence d'un script ;
  • mettent en relief les données et les résultats : entrées et sorties de la fonction ;
  • permettent la réutilisation : mécanisme de l'import ;
  • décomposent une tâche complexe en tâches plus simples : conception de l'application.

Ces avantages sont illustrés sur la figure 5.1 qui utilise entre autres la notion d'import, mécanisme très simple qui permet de réutiliser des fichiers de fonctions, souvent appelés modules ou bibliothèques

Image non disponible
Figure 5.1 - Les avantages de l'utilisation des fonctions

5-1. Définition et syntaxe

Une fonction est un ensemble d'instructions regroupées sous un nom et s'exécutant à la demande

On doit définir une fonction à chaque fois qu'un bloc d'instructions se trouve à plusieurs reprises dans le code ; il s'agit d'une « factorisation de code ».

La définition d'une fonction se compose :

  • du mot clé def suivi de l'identificateur de la fonction, de parenthèses entourant les paramètres de la fonction séparés par des virgules, et du caractère « deux-points » qui termine toujours une instruction composée ;
  • d'une chaîne de documentation (ou docstring) indentée comme le corps de la fonction ;
  • du bloc d'instructions indenté par rapport à la ligne de définition, et qui constitue le corps de la fonction.

Le bloc d'instructions est obligatoire. S'il est vide, on emploie l'instruction pass.

La documentation, bien que facultative, est fortement conseillée.

 
Sélectionnez
def afficheAddMul(a, b) :
    """Calcule et affiche :
    - la somme de a et b,
    - le produit de a et b.
    """
 
Sélectionnez
somme = a + b
produit = a * b
print("La somme de", a, " et", b, " est", somme, "et le produit", produit)

5-2. Passage des arguments

5-2-1. Mécanisme général

Passage par affectation : chaque paramètre de la définition de la fonction correspond, dans l'ordre, à un argument de l'appel. La correspondance se fait par affectation des arguments aux paramètres.

Image non disponible
Figure 5.2 - Passage par affectation des arguments d'appel aux paramètres de définition

5-2-2. Un ou plusieurs paramètres, pas de retour

Exemple sans l'instruction return, ce qu'on appelle souvent une procédure(15). Dans ce cas la fonction renvoie implicitement la valeur None :

 
Sélectionnez
def table(base, debut, fin) :
    """Affiche la table de multiplication des <base> de <debut> à <fin>."""
    n = debut
    while n <= fin :
        print(n, 'x', base, '=', n * base)
        n += 1

# exemple d'appel :
table(7, 2, 8)
# 2 x 7 = 14 3 x 7 = 21 4 x 7 = 28 5 x 7 = 35 6 x 7 = 42 7 x 7 = 49 8 x 7 = 56

# autre exemple du même appel, mais en nommant les paramètres ;
table(base=7, debut=2, fin=8)

5-2-3. Un ou plusieurs paramètres, un ou plusieurs retours

Exemple avec utilisation d'un return unique :

 
Sélectionnez
from math import pi

def cube(x) :
    """Retourne le cube de l'argument."""
    return x**3

def volumeSphere(r) :
    """Retourne le volume d'une sphère de rayon <r> ;"""
    return 4.0 * pi * cube(r) / 3.0

# Saisie du rayon et affichage du volume
rayon = float(input('Rayon : '))
print("Volume de la sphère =", volumeSphere(rayon))

Exemple avec utilisation d'un return multiple :

 
Sélectionnez
import math

def surfaceVolumeSphere(r) :
    surf = 4.0 * math.pi * r**2
    vol = surf * r/3
    return surf, vol

# programme principal
rayon = float(input('Rayon : '))
s, v = surfaceVolumeSphere(rayon)
print("Sphère de surface { :g} et de volume { :g}".format(s, v))

5-2-4. Passage d'une fonction en paramètre

Puisqu'en Python une variable peut référencer une fonction, on peut transmettre une fonction comme paramètre :

 
Sélectionnez
>>> def f(x):
...     return 2*x+1
...
>>> def g(x):
...     return x//2
...
>>> def h(fonc, x):
...     return fonc(x)
...
>>> h(f, 3)
7
>>> h(g, 4)
2

5-2-5. Paramètres avec valeur par défaut

Il est possible de spécifier, lors de la déclaration, des valeurs par défaut à utiliser pour les arguments. Cela permet, lors de l'appel, de ne pas avoir à spécifier les paramètres correspondants.

Il est également possible, en combinant les valeurs par défaut et le nommage des paramètres, de n'indiquer à l'appel que les paramètres dont on désire modifier la valeur de l'argument. Il est par contre nécessaire de regrouper tous les paramètres optionnels à la fin de la liste des paramètres.

 
Sélectionnez
>>> def accueil(nom, prenom, depart="MP", semestre="S2"):
...     print(prenom, nom, "Département", depart, "semestre", semestre)
...
>>> accueil("Student", "Joe")
Joe Student Département MP semestre S2
>>> accueil("Student", "Eve", "Info")
Eve Student Département Info semestre S2
>>> accueil("Student", "Steph", semestre="S3")
Steph Student Département MP semestre S3

On utilise de préférence des valeurs par défaut non modifiables (int, float, str, bool, tuple) car la modification d'un paramètre par un premier appel est visible les fois suivantes.

Si on a besoin d'une valeur par défaut qui soit modifiable (list, dict), on utilise la valeur prédéfinie None et on fait un test dans la fonction avant modification :

 
Sélectionnez
def maFonction(liste=None) :
    if liste is None :
        liste = [1, 3]

5-2-6. Nombre d'arguments arbitraire : passage d'un tuple de valeurs

Le passage d'un nombre arbitraire d'arguments est permis en utilisant la notation d'un argument final *nom. Les paramètres surnuméraires sont alors transmis sous la forme d'un tuple affecté à cet argument (que l'on appelle généralement args).

 
Sélectionnez
def somme(*args) :
    """Renvoie la somme du tuple <args>."""
    resultat = 0
    for nombre in args :
        resultat += nombre
    return resultat

# Exemples d'appel :
print(somme(23)) # 23
print(somme(23, 42, 13)) # 78

Si la fonction possède plusieurs arguments, le tuple est en dernière position.

Réciproquement, il est aussi possible de passer un tuple (en fait une séquence) à l'appel qui sera décompressé en une liste de paramètres d'une fonction « classique ».

 
Sélectionnez
def somme(a, b, c) :
    return a+b+c

# Exemple d'appel :
elements = (2, 4, 6)
print(somme(*elements)) # 12

5-2-7. Nombre d'arguments arbitraire : passage d'un dictionnaire

De la même façon, il est possible d'autoriser le passage d'un nombre arbitraire d'arguments nommés en plus de ceux prévus lors de la définition en utilisant la notation d'un argument final **nom. Les paramètres surnuméraires nommés sont alors transmis sous la forme d'un dictionnaire affecté à cet argument (que l'on appelle généralement kwargs pour keyword args).

Réciproquement il est aussi possible de passer un dictionnaire à l'appel d'une fonction, qui sera décompressé et associé aux paramètres nommés de la fonction.

 
Sélectionnez
def unDict(**kwargs) :
    return kwargs

# Exemples d'appels
## par des paramètres nommés :
print(unDict(a=23, b=42)) # {'a' : 23, 'b' : 42}

## en fournissant un dictionnaire :
mots = {'d' : 85, 'e' : 14, 'f' :9}
print(unDict(**mots)) # {'e' : 14, 'd' : 85, 'f' : 9}

Si la fonction possède plusieurs arguments, le dictionnaire est en toute dernière position (après un éventuel tuple).

5-3. Espaces de noms

Un espace de noms est une notion permettant de lever une ambiguïté sur des termes qui pourraient être homonymes sans cela. Il est matérialisé par un préfixe identifiant de manière unique la signification d'un terme. Au sein d'un même espace de noms, il n'y a pas d'homonymes :

 
Sélectionnez
>>> import math
>>> pi = 2.718
>>> print(pi) # une valeur de l'espace de nom local
2.718
>>> print(math.pi) # une valeur de l'espace de noms math
3.141592653589793

5-3-1. Portée des objets

On distingue :

  • la portée globale : celle du module ou du fichier script en cours. Un dictionnaire gère les objets globaux : l'instruction globals() fournit un dictionnaire contenant les couples nom:valeur ;
  • la portée locale : les objets internes aux fonctions sont locaux. Les objets globaux ne sont pas modifiables dans les portées locales. L'instruction locals() fournit un dictionnaire contenant les couples nom:valeur.

5-3-2. Résolution des noms : règle LGI

La recherche des noms est d'abord locale (L), puis globale (G), enfin interne (I) (Fig. 5.3) :

Image non disponible
Figure 5.3 - Règle LGI

5-3-2-a. Exemples de portée

Par défaut, tout identificateur utilisé dans le corps d'une fonction est local à celle-ci. Si une fonction a besoin de modifier certains identificateurs globaux, la première instruction de cette fonction doit être :

 
Sélectionnez
global <identificateurs>

Par exemple :

 
Sélectionnez
# x et fonc sont affectés dans le module => globaux

def fonc(y) : # y et z sont affectés dans fonc => locaux
    global x # permet de modifier x ligne suivante
    x = x + 2
    z = x + y
    return z

x = 99
print(fonc(1)) # 102
print(x) # 101
 
Sélectionnez
# x et fonc sont affectés dans le module => globaux
def fonc(y) : # y et z sont affectés dans fonc => locaux
    # dans fonc : portée locale
    z = x + y
    return z

x = 99
print(fonc(1)) # 100
print(x) # 99

# x et fonc sont affectés dans le module => globaux

def fonc(y) : # y, x et z sont affectés dans fonc => locaux
    x = 3 # ce nouvel x est local et masque le x global
    z = x + y
    return z

x = 99
print(fonc(1)) # 4
print(x) # 99

précédentsommairesuivant
Une fonction vaut quelque chose, une procédure fait quelque chose.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2015 Kordeo. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.