Construtor Python faz coisas estranhas com parâmetros opcionais [duplicado]
Possível duplicado:
menos espanto em python: o argumento padrão mutável
Eu quero entender o comportamento e as implicações do python__init__
construtor. Parece que quando existe um parâmetro opcional e você tenta definir um objeto existente para um novo objeto, o valor opcional do objeto existente é preservado e copiado.
Veja um exemplo:
No código abaixo, estou tentando criar uma estrutura de árvore com nós e possivelmente muitos filhos. Na primeira aulaNodeBad
, o construtor possui dois parâmetros, o valor e quaisquer filhos possíveis. A segunda classeNodeGood
leva apenas o valor do nó como parâmetro. Ambos têm umaddchild
método para adicionar um filho a um nó.
Ao criar uma árvore com oNodeGood
classe, funciona conforme o esperado. No entanto, ao fazer a mesma coisa com oNodeBad
classe, parece que uma criança só pode ser adicionada uma vez!
O código abaixo resultará na seguinte saída:
Good Tree
1
2
3
[< 3 >]
Bad Tree
1
2
2
[< 2 >, < 3 >]
Que Pasa?
Aqui está o exemplo:
#!/usr/bin/python
class NodeBad:
def __init__(self, value, c=[]):
self.value = value
self.children = c
def addchild(self, node):
self.children.append(node)
def __str__(self):
return '< %s >' % self.value
def __repr__(self):
return '< %s >' % self.value
class NodeGood:
def __init__(self, value):
self.value = value
self.children = []
def addchild(self, node):
self.children.append(node)
def __str__(self):
return '< %s >' % self.value
def __repr__(self):
return '< %s >' % self.value
if __name__ == '__main__':
print 'Good Tree'
ng = NodeGood(1) # Root Node
rootgood = ng
ng.addchild(NodeGood(2)) # 1nd Child
ng = ng.children[0]
ng.addchild(NodeGood(3)) # 2nd Child
print rootgood.value
print rootgood.children[0].value
print rootgood.children[0].children[0].value
print rootgood.children[0].children
print 'Bad Tree'
nb = NodeBad(1) # Root Node
rootbad = nb
nb.addchild(NodeBad(2)) # 1st Child
nb = nb.children[0]
nb.addchild(NodeBad(3)) # 2nd Child
print rootbad.value
print rootbad.children[0].value
print rootbad.children[0].children[0].value
print rootbad.children[0].children