Passage par référence

DéfinitionRéférence

Le langage Python traite ce qu’on appelle des objets, c’est-à-dire que les données ont la forme d’objets. Une référence est donc un identifiant qui va permettre de cibler un objet. On peut donc dire que les variables sont des références nommées vers des objets.

On peut différencier deux types d’objets : les objets mutables et les objets immutables.

Les objets mutables peuvent changer de valeur (par exemple, une liste pourra changer de valeur mais sa référence restera la même).

Les objets immutables ne peuvent pas changer de valeur si on ne leur affecte pas une nouvelle valeur (les nombres entiers ou les chaînes de caractères par exemple).

Chaque objet a une référence unique. Nous allons par exemple dans ce script chercher avec la commande id la référence d’une variable du nom de eggs :

1
eggs = 1041
2
print (id(eggs))

Le terminal renvoie alors :

1
2253976033200

C’est la référence de l’objet auquel fait référence la variable eggs.

Par logique, on comprend qu’on peut se retrouver dans un cas de figure où plusieurs variables font référence au même objet.

1
var1 = 2
2
var2 = 2
3
print(id(var1))
1
print(id(var2))

Le terminal renvoie alors :

1
2445138788624
2
2445138788624

On voit que la référence (l’id) de var1 est la même que var2 car leur valeur est le même objet (objet qui a pour valeur 2). Cet objet est immutable.

Complément

Maintenant, voyons comment ce que nous avons appris sur les concepts de portées et de variables globales et locales va nous aider. Étudions ensemble ce script :

1
def test (parametre):
2
    print(id(parametre))
3
    parametre.append(1)
4
    parametre.append(2)
5
    print (parametre)
6
liste=[]
7
print (id(liste))
8
test (parametre=liste)
9
print (liste)

Le terminal renvoie :

1
1803970750976
2
1803970750976
3
[1, 2]
4
[1, 2]

On cherche dans ce script à afficher deux variables, la variable paramètre et la variable liste. On comprend que la variable liste est globale puisqu’elle est déclarée dans la portée globale. La variable paramètre quant à elle est inscrite en paramètre de la fonction test. La fonction test va rajouter dans la variable inscrite en paramètre les valeurs 1 et 2, il s’agit donc d’une liste. L’objet qu’est cette liste est mutable. On voit dans les lignes que renvoie le terminal que liste et paramètre se réfèrent au même objet, ils ont la même référence et la même valeur [1, 2]. En fait, lorsqu’on appelle la fonction test(), on indique que paramètre sera égale à la variable globale liste. Ces deux variables portent sur le même objet, la référence étant identique.

On comprend donc qu’on ne crée pas deux objets, mais qu’un seul objet est créé et les deux variables portent sur ce même objet. Si on veut créer deux objets différents, il faut déclarer une variable locale qui ne fera pas référence au même objet que la variable globale test. Par exemple, si on fait :

1
def test (parametre):
2
    liste2=parametre.copy()
3
    print(id(liste2))
4
    liste2.append(3)
5
    liste2.append(4)
6
    print (liste2)
7
liste=[1, 2]
8
print (id(liste))
9
test (parametre=liste)
10
print (liste)

Le terminal renvoie :

1
3001762064896
2
3001762017984
3
[1, 2, 3, 4]
4
[1, 2]

Donc ici, on affecte à la variable liste : [1, 2]. Elle porte donc toujours sur un objet liste. Dans la fonction test, on crée une variable locale liste 2, puis on lui affecte une copie du paramètre qui au moment de la déclaration est égale à liste. « liste 2 » est donc un autre objet. On ajoute à liste 2 (qui contient actuellement [1, 2]) les valeurs 3 et 4. On voit en imprimant liste et liste 2 que ces variables font bien référence à deux objets différents. Mais, sans même avoir besoin d’imprimer les valeurs des variables, le simple fait que les références des deux objets soient différentes prouve qu’il s’agit de deux objets différents.

Le passage par référence va vous permettre de comprendre et d’éviter de nombreuses erreurs qui pourraient bloquer votre programme. Vous pourrez identifier les objets sur lesquels portent les variables, et ne pas tomber dans un piège où plusieurs variables portent sur le même objet. Il est donc important de le maîtriser dans le but de clairement cibler les objets qui sont la base du Python.