2017-09-14 88 views
7

在此代码:为什么不同的变量名称会得到不同的结果(python2.7)?

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y): 
     return i 
    results.append(inner) 

for i in results: 
    print i(None) 

的输出为 “函数内在0x107dea668”

如果我改变到其他信,例如:

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y): 
     return i 
    results.append(inner) 

for j in results: 
    print j(None) 

输出为“4”


回答

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y): 
     print "in inner:%s " % id(i) 
     return i 
    results.append(inner) 

# i -> 4 
for i in results: 
    # i -> func inner 
    print "i: %s" % i 
    print "in loop: %s " % id(i) 

    # func inner <===> A 
    # i == A -> return i -> return A, so when call funtion inner, will return itself 
    # print "call: %s" % i(None) 

    print "call: %s" % i(None)(None)(None) 
    print "------------------------------" 

I:在内部4315172208
:4315172208
呼叫功能内在0x101344d70
在循环:在内部4315172208
:4315172208
在内:功能内在0x101344d70

I:在内部4315172328
:4315172328
在内:4315172328
在内:在0x101344de8
在循环函数内4315172328
呼叫:函数内在0x101344de8

I:功能在0x101344e60内
在循环:4315172448
在内:4315172448
在内:4315172448
在内:4315172448
呼叫:函数内在0x101344e60

I:函数内在0x101344ed8
在循环:在内部4315172568
:4315172568
在内:4315172568
在内:4315172568
呼叫:函数内在0x101344ed8

+3

你刚认识的'i' –

+0

有关懒惰的评价:https://stackoverflow.com/questions/42805800/generator-comprehension-different-output-from-list-comprehension –

+0

这是不相关懒惰的评估,这是一个背景问题。懒惰评估只是在需要时评估,而不是在哪里评估。 –

回答

1

i变量返回inner函数保留它的值,而不是它分配的最后一个上下文。

如果调试代码,使用inner函数中的断点,如果在调用函数之前选择前一帧/上下文(图中左下角),图片将变得更清晰。

当您使用i时,它被分配在第二个for内部,因此它将具有一个函数作为其值(在图1中用黄色突出显示)。现在

Figure 1

,如果你使用j,可变i将继续从以前的背景下其最后的值:在for在列表(图2)。

Figure 2

1

事实上,当你在结果中使用j时,变量i保持为4,由于第一次循环后,我保持数字4;

但是,如果您在结果中使用i,那么我指的是存储在结果中的函数。在你开始打电话之前,我并不固定。正如@ Jean-FrançoisFabre所言,懒惰的评价。

此外,如果你想内部函数来存储每个i当来自1-4环,您我应该存储在相关范围,使用局部功能;

from functools import partial 

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(i, y): 
     return i 


    results.append(partial(inner, i)) 

for i in results: 
    print(i(None)) 

这会给你的

1 
2 
3 
4 

这是更有意义的结果。

3

您定义的inner函数包含一个自由变量,指向全局变量i。这也许是一个例子像这样清晰的:

def inner(y): 
    return i 

i = 1 
print inner(None) 

i = 2 
print inner(None) 

它打印1,然后2

在你的第一个例子中,在调用inner的时间,i已经是函数的值,所以当i(即inner)被调用时打印的是什么。

在第二示例中,在呼叫到inner时,i具有值4,因此这是当j(这是inner)被称为什么被打印。

一个明确的方式来表达你大概想要在这里是使用部分评估的功能,如另一answer推荐。另一种方法是使用封闭函数来创建闭包。像这样:

results = [] 
for i in [1, 2, 3, 4]: 
    def outer(k): 
     def inner(y): 
      return k 
     return inner 
    results.append(outer(i)) 

for i in results: 
    print i(None) 

这将打印1至4大概你想要的。

甲小动作有时在Python使用是使用变量的默认值作为单元格包含一个值:

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y, i = i): 
     return i 
    results.append(inner) 

for i in results: 
    print i(None) 

这也打印在1至4

相关问题