2

以下是三个python代码:

======= 1号=======

def foo(x, items=[]):
    items.append(x)
    return items

foo(1)  #return [1]
foo(2)  #return [1,2]
foo(3)  #return [1,2,3]

====== 2号========

def foo(x, items=None):
    if items is None:
        items = []
    items.append(x)
    return items

foo(1)  #return [1]
foo(2)  #return [2]
foo(3)  #return [3]

====== 3号=======

def foo(x, items=[]):
    items.append(x)
    return items

foo(1)    # returns [1]
foo(2,[]) # returns [2]
foo(3)    # returns [1,3]

对于代码 1,由于items没有提供 的值,我认为它应该始终采用默认值 []。但是该参数的items行为类似于静态变量,保留其值以供后续使用。No.2 的代码按我的预期执行:每次调用 foo 时,items取默认值None。至于代码 3,我完全不知道。为什么上面三段代码的执行方式如此不同?你可以解释吗?谢谢你。

PS:我正在使用 python 3.3.1

4

3 回答 3

2

“Least Astonishment”和可变默认参数

这个 stackoverflow 帖子回答了您的问题,因为 Python 函数是具有状态的对象,“item”命名参数在多个调用之间保留状态。

它有它的用途:

def calculate(a, b, c, memo={}):
    try:
        value = memo[a, b, c] # return already calculated value
    except KeyError:
        value = heavy_calculation(a, b, c)
        memo[a, b, c] = value # update the memo dictionary
    return value

如此处所述http://effbot.org/zone/default-values.htm

于 2013-08-22T01:20:50.653 回答
1

源代码[]不是一个值。这是一个计算结果为列表的表达式。如果你评估一次,你会得到一份清单;如果你多次评估它,你会得到多个列表。要实现的关键是默认参数只计算一次默认表达式并存储它;因此,如果默认参数是一个列表,那么每次调用它总是相同的列表。

于 2013-08-22T01:16:06.757 回答
0

似乎项目的默认列表对象的定义发生在函数定义时。如果您传入某些内容,items 变量将使用您传入的对象,否则默认为该默认列表对象。

因为示例 1 和 3 没有重新定义默认列表对象(而示例 2 确实每次都将列表设置为空),所以您对其所做的更改是累积的。在示例 3 中,传入一个单独的空列表对象以用于 items 变量意味着您第二次执行该函数不会对您定义的默认列表对象产生任何影响。

于 2013-08-22T01:16:36.730 回答