Un défaut est évalué à la définition, jamais à l'appel.A default is evaluated at definition, never at the call.
Au premier numéro, on a croisé def f(x=[]) comme un symptôme : la liste qui ne se vide jamais. On va maintenant le disséquer comme un mécanisme — et découvrir que le piège n'a rien à voir avec les listes. Il tient à un seul décalage : en Python, l'expression par défaut d'un paramètre s'exécute quand la ligne def est lue, une fois pour toutes, pas à chaque appel de la fonction. Venu d'un langage typé, on suppose l'inverse : que le défaut est « la valeur utilisée quand l'argument manque », fraîche à chaque fois. Faux.In the first issue we met def f(x=[]) as a symptom: the list that never empties. Now we dissect it as a mechanism — and find the trap has nothing to do with lists. It comes down to one gap: in Python, a parameter's default expression runs when the def line is read, once and for all, not on each call of the function. Coming from a typed language, you assume the opposite: that the default is 'the value used when the argument is missing', fresh each time. Wrong.
import time def stamp(t=time.time()): # time.time() est appelé UNE fois, ici, à la définition return t # ... trois secondes plus tard ... stamp() # renvoie l'instant de la DÉFINITION, pas celui de l'appel stamp() # ... et le même instant, encore : le défaut ne se recalcule jamais
La ligne def n'est pas qu'une déclaration : c'est une instruction qui s'exécute. Elle évalue chaque expression par défaut sur-le-champ, et range le résultat sur l'objet-fonction. L'appel, lui, ne fait que relire ce résultat.The def line isn't just a declaration: it's a statement that runs. It evaluates each default expression on the spot, and stores the result on the function object. The call merely re-reads that result.
Devant un def f(x=EXPR), demande-toi : EXPR est évaluée maintenant, une fois. Si EXPR produit un objet mutable, tous les appels sans argument le partagent. Si EXPR lit l'heure, une config, un compteur — c'est la valeur au moment de la définition qui est gelée, pour toujours.Facing a def f(x=EXPR), ask yourself: EXPR is evaluated now, once. If EXPR yields a mutable object, every argument-less call shares it. If EXPR reads the clock, a config, a counter — the value at definition time is frozen, forever.
Le №01 a posé « un nom lie un objet », le №02 « le type décide de la mutabilité ». Le défaut par argument est le premier lieu où ces deux idées se combinent en un bug de production : un objet, lié une fois, mutable, partagé à l'insu de l'appelant. C'est le pont vers le Vol. II, où l'on demandera pour de bon : qui d'autre tient cette référence ?№01 laid down 'a name binds an object', №02 'the type decides mutability'. The default argument is the first place these two ideas combine into a production bug: one object, bound once, mutable, shared without the caller's knowledge. It's the bridge to Vol. II, where we'll ask for real: who else holds this reference?