Passer un objet, c'est lui coller un second nom — pas le copier.Passing an object sticks a second name on it — it doesn't copy it.
Le Vol. I a établi qu'un nom lie un objet sans le copier. Le Vol. II en tire la conséquence qui hante le code réel : si l'assignation ne copie pas, alors plusieurs noms tiennent le même objet — et l'événement d'aliasing le plus courant, ce n'est pas b = a, c'est l'appel de fonction. Quand tu passes facture à ajouter_total, le paramètre lignes ne reçoit pas une copie : il devient un alias, un second nom sur la même liste. Muter par ce nom mute l'objet de l'appelant. Aucune ligne avec un = n'a été écrite chez lui, et pourtant sa donnée a changé.Vol. I established that a name binds an object without copying it. Vol. II draws the consequence that haunts real code: if assignment doesn't copy, then several names hold the same object — and the most common aliasing event isn't b = a, it's the function call. When you pass facture to ajouter_total, the parameter lignes doesn't receive a copy: it becomes an alias, a second name on the same list. Mutating through that name mutates the caller's object. No line with an = was written on their side, yet their data changed.
def ajouter_total(lignes): lignes.append("TOTAL") # on « ajoute juste » au paramètre return lignes facture = ["A", "B"] ajouter_total(facture) print(facture) # ['A', 'B', 'TOTAL'] — facture a changé, sans =
L'appel a exécuté, en coulisse, lignes = facture. Deux noms, un objet. lignes.append(...) mute cet objet — et facture, qui le désigne aussi, « voit » l'ajout.The call ran, behind the scenes, lignes = facture. Two names, one object. lignes.append(...) mutates that object — and facture, pointing to it too, "sees" the addition.
« Qui d'autre tient une référence sur cet objet que je m'apprête à muter ? » Avant chaque .append, .sort(), obj.x = ... sur un paramètre, demande-toi combien de noms — chez l'appelant, dans une liste, ailleurs — pointent le même objet. Chacun verra ta mutation."Who else holds a reference to this object I'm about to mutate?" Before each .append, .sort(), obj.x = ... on a parameter, ask how many names — in the caller, inside a list, elsewhere — point at the same object. Each will see your mutation.
Python ne passe pas l'argument « par valeur » (une copie, comme un int en C) ni « par référence » (un alias du nom, comme un & en C++). Il passe par assignation : le paramètre est lié au même objet que l'argument. On appelle ça call by sharing. Toute la suite du numéro déplie ce que ça implique.Python passes the argument neither 'by value' (a copy, like an int in C) nor 'by reference' (an alias of the name, like a & in C++). It passes by assignment: the parameter is bound to the same object as the argument. This is called call by sharing. The rest of the issue unfolds what it implies.