首页 > 解决方案 > 为什么在“if False:”块中注释赋值语句会导致差异“NameError”消息?

问题描述

如果我在块中评论了该baz = 4语句,我会收到else 我收到的消息if False:NameError: name 'baz' is not definedNameError: free variable 'baz' referenced before assignment in enclosing scope

我在python中运行Python 3.7.2+

def foo():
 def bar():
  return baz + 1
 if False:
  baz = 4
  pass
 return bar()

foo() 

我希望总是收到消息NameError: name 'baz' is not defined,就像我评论了一样,baz = 4因为该baz = 4语句从未执行过,但实际消息是NameError: free variable 'baz' referenced before assignment in enclosing scope

标签: python

解决方案


该变量baz从未分配过,但根据代码,它存在于本地命名空间中。因此,为它保留了一个条目,因此它不是“未定义”,而是“未分配”。

让我们扩展您的示例:

def foo(b):
    def bar(): return baz
    if b: baz = 4
    return bar, locals()

并使用它:

>>> a, b = foo(0)
>>> c, d = foo(1)
>>> a
<function foo.<locals>.bar at 0x000002320BA6A0D0>
>>> b
{'bar': <function foo.<locals>.bar at 0x000002320BA6A0D0>, 'b': 0}
>>> c
<function foo.<locals>.bar at 0x000002320BA6A268>
>>> d
{'bar': <function foo.<locals>.bar at 0x000002320BA6A268>, 'b': 1, 'baz': 4}
>>> a.__closure__
(<cell at 0x000002320BA3E9A8: empty>,)
>>> c.__closure__
(<cell at 0x000002320BA3E948: int object at 0x000000006E2C6140>,)
>>> a.__closure__[0].cell_contents
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Cell is empty
>>> c.__closure__[0].cell_contents
4
>>> foo.__code__.co_cellvars
('baz',)

这里我们看到了区别:在第一种情况下,闭包中的单元格保持为空,在第二种情况下,它包含一个 int 对象(即 4)。


推荐阅读