我写了以下玩具:
def foo():
x = 5
def foo2():
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
print("CP 1")
print("x =", x)
print("CP 2")
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
foo2()
foo()
print("-----------------------")
def foo():
x = 5
def foo2():
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
print("CP 1")
print("x =", x)
print("CP 2")
del x
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
foo2()
foo()
将产生以下输出:
Locals: {'x': 5}
Vars: {'x': 5}
dir: ['x']
CP 1
x = 5
CP 2
Locals: {'x': 5}
Vars: {'x': 5}
dir: ['x']
-----------------------
Locals: {}
Vars: {}
dir: []
CP 1
Traceback (most recent call last):
File "testing.py", line 34, in <module>
foo()
File "testing.py", line 32, in foo
foo2()
File "testing.py", line 26, in foo2
print("x =", x)
UnboundLocalError: local variable 'x' referenced before assignment
>>>
请注意,即使在两个版本相同的代码区域内,第二版的行为也要进行修改(因此应该产生相同的结果)。根据第一版,由于x确实存在于本地名称空间中,因此del语句不应该成为问题。
问题:
1)第一版或第二版是否正确? x是否应该存在于命名空间中?
2)对此行为有解释还是错误?
(遵循2:3)第二版应该没有错误运行还是应该崩溃?]
del x
触发解释器隐藏在x
框架之外定义的非本地foo2()
变量。
如果在相同位置用del x
替换x = ...
,将获得相同的效果。
原因是x
实际上与foo2()
处于同一级别,并且在del x
期间到达foo2()
时,解释器决定不为本地变量保留名称x
x
,因此它不会使用外部名称更新您的locals()
。在x
中移动foo2()
分配将使x
成为真正的local
,因此出现在locals()
中:
def foo():
def foo2():
x = 5
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
print("CP 1")
print("x =", x)
print("CP 2")
del x
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
foo2()
foo()
Locals: {'x': 5}
Vars: {'x': 5}
dir: ['x']
CP 1
x = 5
CP 2
Locals: {}
Vars: {}
dir: []
以及声明x
明确引用nonlocal
内部的foo2()
变量:
def foo():
x = 5
def foo2():
nonlocal x
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
print("CP 1")
print("x =", x)
print("CP 2")
del x
print("Locals: ", locals())
print("Vars: ", vars())
print("dir: ", dir())
foo2()
foo()
Locals: {'x': 5}
Vars: {'x': 5}
dir: ['x']
CP 1
x = 5
CP 2
Locals: {}
Vars: {}
dir: []
以下帖子为我解决了它:
https://amir.rachum.com/blog/2013/07/09/python-common-newbie-mistakes-part-2/
我想突出显示:
“第一个误解是Python是一种解释型语言(很棒,我认为我们都可以同意),是逐行执行的。实际上,Python是按语句执行的。理解我的意思后,转到您喜欢的shell(我希望您没有使用默认的shell),然后键入以下内容:
def foo():
按Enter。如您所见,shell没有提供任何输出,显然正在等待您继续执行功能定义。“
这是我困惑的根源。
感谢@ norok2,将我引到这篇文章中。
也有帮助)