python - 使用 try/except 时 Python 中奇怪的变量作用域

标签 python

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_FASTSTORE_FAST,而不是 LOAD_GLOBALSTORE_GLOBALPython 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/

相关文章:

python - 在 C 扩展中使用 Python 列表

python - Scrapy - 抓取选定的 div

python - 基本 Python 数据结构接口(interface)的测试

python - 具有计算颜色的 Hexbin 图

python - 如何检测装饰器是否已应用于方法或函数?

python - 从 date_range 中以特定格式提取日期

python - python 嵌套类变量

python - 从 ColumnDataSource 中选取 Bokeh HoverTool 输出的数据

python - 如何使用 matplotlib 紧密布局与 Figure?

python - 如何从一个链接生成已解析的项目以及同一项目列表中其他链接的其他已解析的项目