可能重复:
“Least Astonishment” in Python: The Mutable Default Argument
编辑:这与recusion无关,只是可变的默认参数功能:"Least Astonishment" and the Mutable Default Argument
非常感谢
我在win7 64bit机器上使用python 2.7.2并且有一个递归函数作用于lxml元素,该函数如下所示:
def recursive_search(start, stack = []):
for element in start.getchildren():
if condition1(element):
stack = recursive_search(element, stack)
elif condition2(element)
stack.append(element)
else:
pass
return stack
当我第一次使用以下方法调用该函数时:
output = recursive_search(starting_element)
它工作正常,我得到了我的期望,但如果我用同样的命令再次调用它,我会得到两倍的期望,就好像我打电话:
output += recursive_search(starting_element)
或者好像堆栈是全局变量。如果我第三次调用它,我会得到3倍的输出等等。
如果我打电话:
output = recursive_search(starting_element, [])
然后我可以根据自己的喜好多次调用它,但是我没有得到异常的行为。
同样,如果我将函数修改为:
def recursive_search(start, stack = []):
if stack == []:
stack = []
for element in start.getchildren():
if condition1(element):
stack = recursive_search(element, stack)
elif condition2(element)
stack.append(element)
else:
pass
return stack
然后我可以致电:
output = recursive_search(starting_point)
我喜欢的次数多次,并没有得到异常行为。
我的问题是:发生了什么 - 这是一个错误还是有一条规则我在将空字符串传递给python中的递归函数时不知道?
答案 0 :(得分:4)
当您使用可变值作为默认参数时,您只获得该默认值的单个实例。如果你的函数修改它,那就是下次调用函数时会传递的函数。
Python文档本身至少有一个对此的引用:http://docs.python.org/release/2.5.2/ref/function.html。请参阅“执行函数定义时评估默认参数值”部分。
答案 1 :(得分:4)
@Mark已经解释过了,所以这是一个解决方案。
def recursive_search(start, stack = None):
if stack is None:
stack = []
for element in start.getchildren():
if condition1(element):
stack = recursive_search(element, stack)
elif condition2(element)
stack.append(element)
else:
pass
return stack
不同之处在于使用默认参数[]
进行一次评估。当它在函数体内时,每次调用都会创建一个新列表。
有些变化,
stack = stack or []
# or
if not stack:
stack = []
不同之处在于,空列表将始终替换为新列表。这意味着如果您传递包含空列表的变量,则在使用这些变体时,该函数将不更改它。
将其与“无”进行比较时,只有在stack
包含“无”时才会替换它。我想这种方法更安全。