foo = 'asdf'
bar = 'asdf'
foobar = 'asdf'
def test():
def get_foo():
print 'foo = ' + foo
def get_bar():
try:
print 'bar = ' + bar
except Exception as e:
print 'nobody set bar :('
def get_foobar():
try:
foobar
except Exception as e:
print e
foobar = "nobody set foobar :("
print foobar
print 'trying to get foo'
get_foo()
print '\ntrying to get bar'
get_bar()
print '\ntrying to get foobar'
get_foobar()
test()
当我运行这个时,我得到这个:
trying to get foo
foo = asdf
trying to get bar
bar = asdf
trying to get foobar
local variable 'foobar' referenced before assignment
nobody set foobar :(
我设置了三个变量:foo、bar、foobar。然后,我使用三个嵌套函数将它们打印出来:get_foo、get_bar 和 get_foobar。
get_foo 只是打印 foo get_bar 打印 bar 并检查异常 get_foobar 使用 try-except 来确保 foobar 在打印之前已设置。
不知何故,get_foobar 失败了?!
最佳答案
将行 global foobar
添加到 get_foobar()
的顶部
这告诉字节码编译器您要使用全局范围而不是局部范围来引用此函数中的变量。
赋值隐式地将变量的作用域更改为整个函数作用域的局部作用域。
在字节码中:
## code input (local)
def test():
print foobar
foobar = 2
## bytecode output
#
# 3 0 LOAD_FAST 0 (foobar)
# 3 PRINT_ITEM
# 4 PRINT_NEWLINE
#
# 4 5 LOAD_CONST 1 (2)
# 8 STORE_FAST 0 (foobar)
# 11 LOAD_CONST 0 (None)
# 14 RETURN_VALUE
## code input (global)
def test():
global foobar
print foobar
foobar = 2
## bytecode output
#
# 4 0 LOAD_GLOBAL 0 (foobar)
# 3 PRINT_ITEM
# 4 PRINT_NEWLINE
#
# 5 5 LOAD_CONST 1 (2)
# 8 STORE_GLOBAL 0 (foobar)
# 11 LOAD_CONST 0 (None)
# 14 RETURN_VALUE
请注意使用 LOAD_FAST
和 STORE_FAST
,而不是 LOAD_GLOBAL
和 STORE_GLOBAL
。 Python dis module documentation有一个操作码列表供引用。
您可以使用此代码快速转储函数的字节码:
import compiler, dis
code = compiler.compile('''
def test():
print foobar
foobar = 2
''', '__main__', 'exec')
dis.dis(code.co_consts[1])
关于python - 使用 try/except 时 Python 中奇怪的变量作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21565109/