我一直在业余时间通过在线练习(这是来自伯克利的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语句时退出框架吗?
答案 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