Python构造函数使用可选参数做奇怪的事情 [英] Python constructor does weird things with optional parameters
问题描述
可能重复:
python中最小的惊讶:可变默认参数
我想了解python __ init __
构造函数的行为和含义。看起来当有一个可选参数,并尝试将现有对象设置为新对象时,将保留并复制现有对象的可选值。
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.
看一个例子:
在下面的代码中,我试图做一个树结构的节点和可能许多孩子。在第一个类 NodeBad
中,构造函数有两个参数,值和任何可能的子项。第二个类 NodeGood
仅将节点的值作为参数。两者都有一个 addchild
方法来添加一个子节点。
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.
$ c> NodeGood 类,它按预期工作。但是,当使用 NodeBad
类做同样的事情时,似乎一个孩子只能添加一次!
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?
下面是示例:
#!/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 = []):
,同一个列表 []
将在每次通过调用代码使用可选参数时传递到方法中。
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.
所以基本上你应该只使用不可变的日期类型,例如 None
作为可选参数的默认值。例如:
So basically you should only use immutable date types such as None
for the default value of an optional argument. For example:
def __init__(self, value, c=None):
然后你可以在方法体中创建一个新的列表:
Then you could just create a new list in the method body:
if c == None:
c = []
这篇关于Python构造函数使用可选参数做奇怪的事情的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!