为什么不同的变量名会得到不同的结果(python2.7)?

时间:2017-09-14 15:58:18

标签: python for-loop

在此代码中:

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:函数内部在0x101344d70
循环中:4315172208
内在:4315172208
内在:4315172208
内在:4315172208
call:函数内部在0x101344d70

i:函数内部在0x101344de8
在循环中:4315172328
在内心:4315172328
在内心:4315172328
在内心:4315172328
call:函数内部在0x101344de8

i:函数内部在0x101344e60
in loop:4315172448
在内心:4315172448
在内心:4315172448
在内心:4315172448
call:函数内部在0x101344e60

i:函数内部在0x101344ed8
循环中:4315172568
在内心:4315172568
在内心:4315172568
在内心:4315172568
call:函数内部在0x101344ed8

3 个答案:

答案 0 :(得分:3)

您定义的inner函数包含一个引用全局变量i的自由变量。在这样的例子中,这可能更清楚:

def inner(y):
    return i

i = 1
print inner(None)

i = 2
print inner(None)

打印1然后打印2

在您的第一个示例中,在调用inner时,i的值为函数,因此在i时打印的是inner。 {1}})被调用。

在第二个示例中,在调用inner时,i的值为4,因此jinner时打印的内容为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) 调用。

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

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。

Python中有时使用的一个小技巧是使用变量的默认值作为包含值的单元格:

$transitions.onStart({}, function (transition) {
    $rootScope.previousState = transition.from();
});

也打印1到4。

答案 1 :(得分:1)

实际上,当你在结果中使用j时,变量i仍然是4,因为在第一次循环之后,i保持为4;

但是如果你在结果中使用i,我指的是存储在结果中的函数。直到你开始调用它我才会被修复。正如@ Jean-FrançoisFabre所说,懒惰的评价。

另外,如果你想在1-4中循环时存储每个i的内部函数,你应该将i存储在相关的范围中,使用 partial < / strong>功能;

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

更有意义。

答案 2 :(得分:1)

i函数中返回的变量inner保留其分配的最后一个上下文的值。

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

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

Figure 1

现在,如果您使用j,变量i将保留上一个上下文的最后一个值:列表上的for(图2)。

Figure 2