具体什么时候删除功能范围(框架)?

时间:2019-01-16 12:35:11

标签: python python-3.x

我一直在业余时间通过在线练习(这是来自伯克利的CS61A)学习一些Python。我现在正在尝试获得一种直观的框架感,但是显然,我仍然没有。

def print_sums(n):
    print(n)
    def next_sum(k):
        return print_sums(n + k)
    return next_sum

print_sums(1)(3)(5)

我认为当上面的代码运行时,它首先将名称print_sums绑定到功能对象print_sums(n)[parent = Global]。

运行 print_sums(1)(3)(5)时,首先评估粗体中的函数调用。

框架f1:现在创建print_sums [parent = Global]。现在是我们当前的框架。现在,名称next_sum已绑定到功能对象next_sum(k)[parent = f1]。

然后print_sums(1)返回next_sum。

我认为,发生上述情况时,代码将“看起来”(至少对计算机而言),就像这样:

def print_sums(n):
    print(n)
    def next_sum(k):
        return print_sums(n + k)
    return next_sum

next_sum(3)(5)

现在,由于函数调用print_sums(1)返回了一个值,所以我也认为当前帧现在又回到了全局。

现在,计算机尝试运行next_sum(3),,但是由于next_sum是f1中定义的名称,并且不在Global中,因此Python不应沿着'the未分配next_sum?'

我想我想学习的是Python到底何时退出框架,不是在唤起return语句时退出框架吗?

2 个答案:

答案 0 :(得分:2)

通常在退出框架时会删除框架本身,这在您认为确实会发生时会发生,return语句很常见。在该框架中定义的值可以存在于框架之外。

代码不像您建议的那样“看起来”如下:

def print_sums(n):
    print(n)
    def next_sum(k):
        return print_sums(n + k)
    return next_sum

next_sum(3)(5)

因为正如您所说,next_sum未在全局范围内定义。 print_sums(1)返回未绑定任何变量名的函数对象。

类似地,如果您具有功能:

def foo():
    x = 1 + 2
    return x

然后print(foo())不会抱怨x没有定义。确实,变量名与其他作用域无关。您可以将其更改为新名称或将其完全删除,其效果将相同:

def foo():
    return 1 + 2

在另一个不同但相关的注解中,函数对象next_sum(或print_sums(1))在其闭包中持有对n值的引用:

print(print_sums(13).__closure__[0].cell_contents)  # 13

答案 1 :(得分:0)

也许这可以帮助您:

def print_sums(n):
"""
stateless function.
n is a local var and is destroyed after the return of the function.
(but the value of n has influence on the definition of the function "next_sum".)
"""
print(n)
def next_sum(k):
    return print_sums(n + k)
return next_sum

print_sums(1)(3)(5)

# run it once
print_sum_with_offset_1 = print_sums(1) # print 1, the local n in the function is 1
# back in the global scope -> the value n=1 exists only(!) in the definition of print_sum_with_offset_1.
print_sum_with_offset_4 = print_sum_with_offset_1(3)
print_sum_with_offset_4(5)

# this was just to show, that print_sums(..) is stateless
print_sum_with_offset_3 = print_sums(3) # print 3, because given n is 3