Avant d'avoir l'audace de déposer un rapport de bogue, j'ai pensé vérifier mes hypothèses parmi les Pythonistes plus sages ici. J'ai rencontré un cas déconcertant aujourd'hui, alors je l'ai réduit à un petit exemple, présenté ci-dessous :
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
A little script to demonstrate that a function won't re-initialize its
list parameters between calls, but instead allows them to retain state.
"""
def bleedscope(a=[], b=[]):
"""
On each call, unless explicitly passed, both `a` and `b` should be
initialized as empty lists.
"""
c = a
if b:
c.extend(b)
return len(c)
x = bleedscope(b=[1])
print x # Should be 1, as expected.
x = bleedscope(b=[2])
print x # Expect also to be 1, but it's 2. `a` is retained.
x = bleedscope(a=[1])
print x # Now 1 as expected.
x = bleedscope(b=[3])
print x # 1 as expected? No, it's 3! Insanity!
Je pensais que les arguments de fonction étaient locaux dans la portée de la fonction, et qu'ils étaient ramassés à la fin d'un appel de fonction, sans jamais conserver d'état entre eux. J'ai testé le script ci-dessus sur Python 2.5.2 et Python 2.6.1, cependant, et ma compréhension ne les résultats. Argument a
conserve certainement l'état entre la plupart de ces appels ; le plus perplexe étant l'appel final à bleedscope
où il saute l'état de l'appel précédent et revient à l'état à la fin du deuxième appel (c'est-à-dire, [1, 2]
). [Je vous suggère de l'exécuter dans votre débogueur préféré pour le constater par vous-même. Si vous n'en avez pas, je suggère Winpdb comme un solide débogueur Python autonome FOSS].
Qu'est-ce qui se passe ici ?