Arguments Mutables des Fonctions

Python propose une variété de types de données, dont certains peuvent être modifiés après leur création et d'autres non. Lorsqu'on parle de types qui peuvent être modifiés, on les appelle des types "mutables". À l'inverse, ceux qui ne peuvent pas être changés sont appelés types "immutables".

Types Mutables

Les types mutables les plus courants sont les list, les dict et les set. Voici un exemple d'une liste :
fruits = ['apple', 'banana', 'cherry']
print(fruits, type(fruits))  # ['apple', 'banana', 'cherry'] <class 'list'>
Avec une list, vous pouvez modifier ses éléments, en ajouter de nouveaux ou en supprimer :
fruits[1] = 'blueberry'       # Remplace 'banana' par 'blueberry'
fruits.append('dragonfruit')  # Ajoute 'dragonfruit' à la fin de la liste
print(fruits)                 # ['apple', 'blueberry', 'cherry', 'dragonfruit']

Types Immutables

À l'inverse, les int, float, string et tuple sont des exemples de types immutables. Une fois créés, vous ne pouvez pas changer leur contenu. Voici un exemple avec une string :
message = 'hello'
print(message, type(message))  # hello <class 'str'>
Si vous essayez de modifier une partie de la string, Python ne vous le permettra pas :
message[0] = 'H'  # Essayer de changer 'h' en 'H' provoquera une TypeError
Comment se fait-il que int soit immutable ? Ne peut-on pas changer sa valeur avec += ou -= ?
Lorsque nous parlons de mutabilité en Python, nous faisons référence à la possibilité de modifier la valeur réelle stockée en mémoire. Par exemple, avec une liste, nous pouvons changer un élément, et c'est toujours la même liste en mémoire.
Les entiers (int) en Python sont immuables. Cela signifie que la valeur en mémoire ne peut pas être modifiée. Si nous avons un entier a = 5 et que nous effectuons une opération comme a += 2, il peut sembler que nous avons changé a. Cependant, Python a en réalité créé un nouvel objet en mémoire avec la valeur 7 et a mis à jour a pour qu'il pointe vers ce nouvel objet. Le 5 original n'a pas été modifié en mémoire, ce qui explique pourquoi les int sont considérés comme immuables.
a = 5
print(id(a))  # Affiche l'identifiant de a. Supposons que c'est 1001

a += 2
print(a)      # Affiche 7
print(id(a))  # Affiche un identifiant différent, disons 1002
La fonction id en Python renvoie l'identité d'un objet, qui est unique et constante pendant la durée de vie de l'objet. Ainsi, lorsque nous constatons que l'identité de a a changé après l'opération a += 2, c'est un signe clair que a pointe désormais vers un nouvel objet en mémoire. L'entier original 5 n'a pas été modifié, ce qui confirme que les entiers sont bien immuables en Python.

Arguments Mutables dans les Fonctions

Lorsque nous passons un objet mutable (comme une liste) à une fonction, Python fournit à la fonction une référence à cet objet. Cela signifie que si la fonction modifie l'objet mutable, cette modification sera visible en dehors de la fonction.
Prenons une fonction qui reçoit une liste et y ajoute un élément :
def add_item(my_list):
    my_list.append('added item')  # Ajoute un nouvel élément à la liste

shopping_list = ['apples', 'bananas', 'cherries']
print(shopping_list)  # Affiche : ['apples', 'bananas', 'cherries']

# Maintenant, nous utilisons la fonction pour ajouter un élément à notre liste de courses
add_item(shopping_list)
print(shopping_list)  # Affiche : ['apples', 'bananas', 'cherries', 'added item']
Comme vous pouvez le voir, après avoir appelé la fonction add_item, notre shopping_list contient un nouvel élément. Cela s'est produit même si nous n'avons pas directement modifié shopping_list en dehors de la fonction.
Cependant, il est important de comprendre que si vous attribuez une nouvelle valeur à l'objet mutable entier à l'intérieur de la fonction, cela n'affectera pas l'objet original. En effet, vous assignez une nouvelle référence à la variable locale de la fonction, sans modifier l'objet initial. Voyons un exemple :
def change_list(my_list):
    my_list = ['entirely', 'new', 'list']  # Cela n'affectera pas la liste originale

shopping_list = ['apples', 'bananas', 'cherries']
change_list(shopping_list)
print(shopping_list)  # Affiche toujours : ['apples', 'bananas', 'cherries']
Même si nous avons appelé la fonction change_list avec shopping_list comme argument, le contenu de shopping_list n'a pas changé. C'est parce qu'à l'intérieur de la fonction, my_list a reçu une nouvelle référence (vers une toute nouvelle liste), tandis que la référence de shopping_list est restée inchangée.
La leçon à retenir est la suivante : lorsque vous passez un objet mutable à une fonction en Python, si la fonction modifie cet objet (comme ajouter un élément à une liste), la modification est permanente et sera visible en dehors de la fonction. Mais si vous attribuez une nouvelle valeur à l'objet entier à l'intérieur de la fonction, cela n'affectera pas l'objet original.
 
To check your solution you need to sign in
Sign in to continue