Python构造函数使用可选参数来做奇怪的事情

可能重复:
最不惊讶的是python:可变的默认参数

我想了解python __init__构造函数的行为和含义。 看起来像有一个可选参数,并且您尝试将现有对象设置为新对象时,现有对象的可选值将被保留并复制。

看一个例子:

在下面的代码中,我试图制作一个带有节点和可能有很多孩子的树结构。 在第一类NodeBad ,构造函数有两个参数,值和任何可能的子NodeBad 。 第二类NodeGood只将该节点的值作为参数。 两者都有一个addchild方法来为节点添加一个子节点。

使用NodeGood类创建树时,它按预期工作。 但是,在NodeBad类中做同样的事情时,似乎只能添加一次子!

以下代码将导致以下输出:

Good Tree
1
2
3
[< 3 >]
Bad Tree
1
2
2
[< 2 >, < 3 >]

Que Pasa?

这是例子:

#!/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

问题是,可选参数的默认值只有一个实例。 例如,如果你说def __init__(self, value, c=[]):那么每次调用代码使用一个可选参数时,同样的list []将被传递给方法。

所以基本上你只能使用不可变的日期类型,例如None作为可选参数的默认值。 例如:

def __init__(self, value, c=None):

然后你可以在方法体中创建一个新的列表:

if c == None:
  c = []

可变的默认参数是混淆的来源。

看到这个答案:“最小的惊讶”和可变的默认参数

链接地址: http://www.djcxy.com/p/28527.html

上一篇: Python constructor does weird things with optional parameters

下一篇: Python class constructor with default arguments