构造函数用可选参数做了奇怪的事情
我想要了解 python __init__
构造函数的行为和含义。似乎当有一个可选参数并且您尝试将现有对象设置为新对象时,现有对象的可选值将被保留并复制。
看一个例子:
在下面的代码中,我试图创建一个带有节点和可能有许多子节点的树结构。在第一个类 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
Possible Duplicate:
least astonishment in python: the mutable default argument
I want to understand of the behavior and implications of the python __init__
constructor. It seems like when there is an optional parameter and you try and set an existing object to a new object the optional value of the existing object is preserved and copied.
Look at an example:
In the code below I am trying to make a tree structure with nodes and possibly many children . In the first class NodeBad
, the constructor has two parameters, the value and any possible children. The second class NodeGood
only takes the value of the node as a parameter. Both have an addchild
method to add a child to a node.
When creating a tree with the NodeGood
class, it works as expected. However, when doing the same thing with the NodeBad
class, it seems as though a child can only be added once!
The code below will result in the following output:
Good Tree
1
2
3
[< 3 >]
Bad Tree
1
2
2
[< 2 >, < 3 >]
Que Pasa?
Here is the Example:
#!/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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是,可选参数的默认值只是一个实例。因此,例如,如果您说
def __init__(self, value, c=[]):
,则每次可选时都会将相同的列表[]
传递到该方法中参数由调用代码使用。因此基本上您应该只使用不可变的日期类型(例如
None
)作为可选参数的默认值。例如:然后您可以在方法主体中创建一个新列表:
The problem is, the default value of an optional argument is only a single instance. So for example, if you say
def __init__(self, value, c=[]):
, that same list[]
will be passed into the method each time an optional argument is used by calling code.So basically you should only use immutable date types such as
None
for the default value of an optional argument. For example:Then you could just create a new list in the method body:
可变的默认参数是造成混乱的根源。
请参阅此答案:“最少惊讶”和可变默认参数
Mutable default arguments are a source of confusion.
See this answer: "Least Astonishment" and the Mutable Default Argument