2015-09-25 31 views
3

测试一些Python代码我尝试下面的代码:`del`陈述和自由变量

(关于Python 3.2+下运行,虽然以前的版本将引发SyntaxErrordel使用和变量被引用在一个封闭的范围)

def x(): 
    N = 200 
    def y(): 
      print(N) 
    del N 
    y() 
x() 
NameError: free variable 'N' referenced before assignment in enclosing scope 

正如你所看到的,Python不提高NameError: global name 'N' is not defined,这让我想知道的一件事是:

del声明我们ED withing函数的封闭范围内删除的喜欢这里,然后y函数嵌套函数内使用,如果在我们的例子N自由变量是通过del声明封闭范围中删除一个自由变量,实际上,它只是删除的内容del该名称的(N)值并将其保持在封闭范围内?

A) Is that why it raises: NameError: free variable 'N' referenced before assignment... rather than NameError: global name 'N' is not defined ?

B) How does del actually delete a name? Does it unbind its value and keep it in a scope ?

我发现了一个类似的案件here

+0

的Python 2.7.3引发'语法错误:无法删除变量“N”嵌套scope'这实际上更有意义比3.2做参照。 –

+0

对不起,你的第一个问题是什么? –

+0

@DanD。 Python 2.7在定义'x'时也会捕获错误,而不是在调用'x'时。我认为它与Python 3中添加的'nonlocal'语句有关,但我不确定这是如何应用的(因为不使用'nonlocal')。 – chepner

回答

1

它的工作原理是这样的:当你写print(N)y但不y分配到N,这意味着在定义y时,巨蟒看起来它的封闭范围将查找名称为N的最近的一个。不要紧前或y定义后分配给N是否会发生,还是它的后面有一个del撤消;它只是寻找N分配存在的最近的封闭范围。在这种情况下,由于N分配里面xy实质上由小纸条说:“当我需要得到N,我会看在x的范围”。

因此,当您实际致电y时,它会在x的范围内寻找N。如果它不在那里,你会得到错误。请注意,如果您在呼叫y后移动N = 100行,则会出现相同的错误,但不包含del

+0

“请注意,您收到此相同的错误,而不'del'如果你调用'y'后移动'N = 200'线”这在技术上是很好!由于控制流程尚未完成任务,因此提出该错误绝对正确。但在我的情况下,控制流达到了分配,并对其进行评估,但随后'del'完全删除了“N”。但是看起来'del'stmt只是没有限制其值200,并将其保留在封闭范围 – direprobs

+0

@direprobs:正如我所说的那样。如果您在'x'的主体中的任意位置*处指定'N' *,那么将'x'不可撤销地标记为“定义了N的范围”,并且这意味着'y'将在'范围内寻找'N' 'x'。不管是否在'y'找到时'N'实际上是否存在,并且无论它不存在的原因是没有达到任务还是任务是但是名字被删除了。分配和删除的名称与尚未分配的名称之间没有区别。 – BrenBarn

+0

所以从技术上讲,当编译器编译函数时,它将'N'绑定到封闭范围,当它被删除,'y'尝试使用'N'时,解释器在封闭范围内查找它并找到它,但是,未分配。这就是为什么它会引发在赋值...之前引用的'NameError:自由变量'N'错误? – direprobs