J'écris une application où les Tags sont liables et il est nécessaire de récupérer toute la chaîne des Tags liés. L'auto-référence n'est pas autorisée. L'exécution du code ci-dessous se termine avec des résultats très étranges:Pourquoi la définition d'une valeur de paramètre par défaut fait-elle de cette fonction une fermeture?
class Tag(object):
def __init__(self, name):
self.name = name
self.links = []
def __repr__(self):
return "<Tag {0}>".format(self.name)
def link(self, tag):
self.links.append(tag)
def tag_chain(tag, known=[]):
chain = []
if tag not in known:
known.append(tag)
print "Known: {0}".format(known)
for link in tag.links:
if link in known:
continue
else:
known.append(link)
chain.append(link)
chain.extend(tag_chain(link, known))
return chain
a = Tag("a")
b = Tag("b")
c = Tag("c")
a.link(b)
b.link(c)
c.link(a)
o = tag_chain(a)
print "Result:", o
print "------------------"
o = tag_chain(a)
print "Result:", o
Résultats:
Known: [<Tag a>]
Known: [<Tag a>, <Tag b>]
Known: [<Tag a>, <Tag b>, <Tag c>]
Result: [<Tag b>, <Tag c>]
------------------
Known: [<Tag a>, <Tag b>, <Tag c>]
Result: []
donc, en quelque sorte, je l'ai créé accidentellement une fermeture. Pour autant que je peux voir, connu aurait dû sortir de la portée et est mort une fois l'appel de fonction terminée.
Si je change la définition de chain_tags() pour définir pas une valeur par défaut, le problème disparaît:
...
def tag_chain(tag, known):
...
o = tag_chain(a, [])
print "Result:", o
print "------------------"
o = tag_chain(a, [])
print "Result:", o
Pourquoi?
Merci pour la réponse claire. Je suis habitué à ce que Python soit beaucoup plus explicite que ça. Si quelqu'un connaît la raison d'être de cette décision, je serais vraiment intéressé de le voir. –