Python函数和空字符串

时间:2012-01-13 16:02:16

标签: python python-2.7

  

可能重复:
  “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中的递归函数时不知道?

2 个答案:

答案 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包含“无”时才会替换它。我想这种方法更安全。