Aller au contenu

Effet de bord

Fonction à effet de bord

Rappelons de quoi il s'agit:

Important

Extrait de wikipedia

En informatique, une fonction est dite à effet de bord (traduction mot à mot de l'anglais side effect, dont le sens est plus proche d'effet secondaire) si elle modifie un état en dehors de son environnement local, c'est-à-dire a une interaction observable avec le monde extérieur autre que renvoyer une valeur.

Par exemple, les fonctions qui modifient une variable non locale ou un argument mutable passé par référence, les fonctions qui effectuent des opérations d'entrées-sorties ou les fonctions appelant d'autres fonctions à effet de bord. Souvent, ces effets compliquent la lisibilité du comportement des programmes et/ou nuisent à la réutilisabilité des fonctions et procédures.

Le caractère muable des listes amène assez naturellement à écrire de telles fonctions à effet de bord: des fonctions qui modifient la liste passée en argument.

Echanger les valeurs de deux éléments d'une liste

Echange en place (avec effet de bord)

Écrire un code possible pour la fonction suivante:

def echange(liste, indice1, indice2):
    """
    liste -- liste d'entiers
    indice1 -- indice d'un élément de liste
    indice2 -- indice d'un élément de liste

    échange les valeurs de liste[indice1] et liste[indice2]
    (fonction à effet de bord, ne renvoie rien)
    """
Un code

Voir ce fichier ipynb (ou sa version html).

Echange sans effet de bord (création d'une nouvelle liste)

Imaginez une fonction permettant comme-ci dessus d'échanger deux éléments dans une liste sans effet de bord.
Quelles différences avec l'exercice précédent?

Un code

Voir ce fichier ipynb (ou sa version html).

Les pairs d'abord

En place (effet de bord)

Écrire un code possible pour le corps de la fonction suivante:

def pairImpair(tab):
    """
    tab -- liste d'entiers

    Place les éléments pairs en début de tableau
    et les éléments impairs en fin de tableau
    (la fonction ne renvoie rien, fonction à effet de bord agissant
    sur la liste passée en argument)
    """

Exemple:

>>> A = [2,3,4,5,6,8]
>>> pairImpair(A)
>>> A
[2, 8, 4, 6, 5, 3]
Une aide

On essaiera de préciser et mettre en oeuvre le principe suivant:

  • une variable gauche est initialisée à 0,
  • une variable droite est initialisée à longueur(tab)-1.
  • Si tab[gauche] est pair, gauche est incrémenté.
  • Si tab[droite] est impair, droite est décrémenté.
  • Si tab[gauche] est impair et tab[droite] est pair, on échange leurs contenus.
Un code possible
def pairImpair(tab):

    gauche, droite = 0, len(tab)-1
    while gauche < droite:
        if tab[gauche] % 2 == 0: gauche += 1
        if tab[droite] % 2 == 1: droite -= 1
        if gauche < droite and tab[gauche] % 2 == 1 and tab[droite] % 2 == 0:
            tab[gauche], tab[droite] = tab[droite], tab[gauche]
            gauche += 1
            droite -= 1


A = [1,2,3,4,5,6]
pairImpair(A)
print(A)

Pour bien comprendre ce code, écrivez les étapes une par une lors d'un appel. Vous pouvez également visualiser les étapes avec python tutor.

En créant une nouvelle liste (sans effet de bord)

Écrire un code possible pour le corps de la fonction suivante:

def pairImpair(tab):
    """
    tab -- liste d'entiers

    renvoie une liste de même contenu que tab 
    mais avec les éléments pairs en début de tableau
    et les éléments impairs en fin de tableau
    (fonction sans effet de bord)
    """
Un principe possible

On peut commencer par placer les éléments pairs dans une nouvelle liste. Puis on ajoute les éléments impairs en fin de cette nouvelle liste.

Un code possible
def pairImpair(tab):
    """
    tab -- liste d'entiers

    renvoie une liste de même contenu que tab 
    mais avec les éléments pairs en début de tableau
    et les éléments impairs en fin de tableau
    (fonction sans effet de bord)
    >>> A = [1,2,3,4,5, 6]
    >>> B = pairImpair(A)
    >>> B
    [2, 4, 6, 1, 3, 5]
    """

    # on crée une liste ne contenant que les éléments pairs:
    nvTab = [element for element in tab if element%2 == 0]

    # on ajoute maintenant en fin de liste tous les éléments impairs:
    for element in tab:
        if element%2 == 1:
            nvTab.append(element)


    return nvTab
Un autre code

La liste des impairs peut être également créée de la même façon que la liste des pairs. On concatène ensuite les deux listes.

def pairImpair(tab):
    """
    tab -- liste d'entiers

    renvoie une liste de même contenu que tab 
    mais avec les éléments pairs en début de tableau
    et les éléments impairs en fin de tableau
    (fonction sans effet de bord)
    """

    # on crée une liste ne contenant que les éléments pairs:
    pairs = [element for element in tab if element%2 == 0]

    # on ajoute maintenant en fin de liste tous les éléments impairs:
    impairs = [element for element in tab if element%2 == 1]


    return pairs + impairs


print(pairImpair([1,2,3,4,5,6]))