经典Py形参陷井
iasybvm <[email protected]> reply-to [email protected] to python-cn <[email protected]> date Sat, Jan 30, 2010 at 19:55 subject [CPyUG] 一段灵异代码,汗。。。
现象
1 class Category(object):
2 def __init__(self, id):
3 self.children = []
4 self.id = id
5 def recurse_for_children(self, node):
6 children = []
7 children.append(node)
8 for child in node.children:
9 if child != self:
10 children_list = self.recurse_for_children(child)
11 children.append(children_list)
12 return children
13 def recurse_normal_children(self, node, children=[]):
14 children.append(node)
15 for child in node.children:
16 if child != self:
17 self.recurse_normal_children(child, children)
18 return children
19 def __str__(self):
20 return "Category %d" % self.id
21
22 def get_flat_list(sequence):
23 result = []
24 for item in sequence:
25 if type(item) == types.ListType:
26 result.extend(get_flat_list(item))
27 else:
28 result.append(item)
29 return result
get_flat_list和 recurse_for_children
加起来应该和get_normal_children等价的。
但是,结果却并不是这样,get_normal_children会给出多得多的结果。
>>> def recurse_for_normal(node, children=[]): ... children.append(node) ... for child in node.children: ... recurse_for_normal(child, children) ... 这一个好一些。 为什么会这样啊?
原因分析
HYRY <[email protected]> reply-to [email protected] to python-cn`CPyUG`华蟒用户组 <[email protected]> date Sat, Jan 30, 2010 at 20:59
Python的经典陷坑:
- 缺省值如果为列表这样的可变对象的话,只会初始化一次,并非每次调用函数都会将children 初始化为[]。
def recurse_normal_children(self, node, children=[]):
看下面的例子:
输出为
[2] [2, 2]
设置初始值是在函数创建时,而不是在函数调用时。
输出为
([1],) 57736168 57736168 57736168
也就是说每次调用test函数并没有创建一个新列表,而是直接使用 创建函数时所创建的那个缺省值列表。因此输出的三个id是一样的。
即在创建函数时以及将缺省值求出来放到func_defaults中去了
一般处置
KDr2 <[email protected]> sender-time Sent at 21:03 (GMT+08:00). Current time there: 9:22 PM. ✆ reply-to [email protected] to [email protected] date Sat, Jan 30, 2010 at 21:03
嗯,一般是
def function(default_arg=None): if default_arg==None:default_arg=[] #....
PS:动态的参数
机械唯物主义 <[email protected]> sender-time Sent at 21:09 (GMT+08:00). Current time there: 9:23 PM. ✆ reply-to [email protected] to [email protected] date Sat, Jan 30, 2010 at 21:09
还有就是动态建立function的时候,如果用到外面的变量,要传进去,不然就会被覆盖掉。
反馈
创建 by -- ZoomQuiet [2010-01-30 13:23:58]