2013-08-22 37 views
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值,我THI nk应该始终采用默认值[]。但参数items的行为类似于一个静态变量,为后续使用保留其值。 No.2的代码按照我的预期执行:每次调用foo时,items取默认值None。至于代码3,我完全不知道。为什么上述三段代码执行得如此不同?你可以解释吗?谢谢。

PS:我使用蟒3.3.1

+0

有无。 1,如果foo只是在没有赋值的情况下被调用,它是这样行事的吗? – Jiminion

+0

在阅读了Python中的“最小惊讶”之后:“可变的默认参数”和相关链接http://effbot.org/zone/default-values.htm,我想我找到了答案。不幸的是,我认为我发现的答案与“最小惊讶”线程和effbot.org网页中的答案不同,以及这个问题中的答案。所以我计划发布自己的答案。但似乎我不允许这样做,也许是因为有些人认为这是一个重复的帖子。 (继续......) – user2384994

+0

我同意这个问题有点重复,但答案决不是重复。因此,我不会接受任何答案,并决定在这里发表我的回答,作为评论,也发表在“最小惊讶”的帖子中。 – user2384994

回答

1

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

0

看来,项目的默认列表对象的定义发生在函数定义时间。如果你传递了一些东西,items变量会使用你传入的对象,但是默认情况下默认是默认的列表对象。

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

2

"Least Astonishment" and the Mutable Default Argument

这个计算器的帖子给出了回答你的问题,因为Python的功能与状态的对象,在“项目”命名参数保留多个调用之间的状态。

它有它的用途:

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