Python:NameError:在封闭范围中赋值之前引用的自由变量're'

时间:2013-05-14 14:00:10

标签: python

我在Python 3.3.1(win7)中有一个奇怪的NameError。

代码:

import re

# ...

# Parse exclude patterns.
excluded_regexps = set(re.compile(regexp) for regexp in options.exclude_pattern)

# This is line 561:
excluded_regexps |= set(re.compile(regexp, re.I) for regexp in options.exclude_pattern_ci)

错误:

Traceback (most recent call last):
  File "py3createtorrent.py", line 794, in <module>
    sys.exit(main(sys.argv))
  File "py3createtorrent.py", line 561, in main
    excluded_regexps |= set(re.compile(regexp, re.I) for regexp in options.exclude_pattern_ci)
  File "py3createtorrent.py", line 561, in <genexpr>
    excluded_regexps |= set(re.compile(regexp, re.I) for regexp in options.exclude_pattern_ci)
NameError: free variable 're' referenced before assignment in enclosing scope

请注意,发生错误的第561行是上面代码中的 second 行。换句话说:re 不是自由变量。它只是正则表达式模块,它可以在第一个行中完美地引用。

在我看来,对re.I的引用导致了问题,但我不知道如何。

3 个答案:

答案 0 :(得分:10)

最有可能的是,你在{em> 第561行以下的某个点分配re(可能是无意中),但是在同一个函数中。这会再现您的错误:

import re

def main():
    term = re.compile("foo")
    re = 0

main()

答案 1 :(得分:8)

回溯中的

“自由变量”表明这是封闭范围内的局部变量。像这样的东西:

 baz = 5

 def foo():
     def bar():
         return baz + 1

     if False:
          baz = 4

     return bar()

这样baz指的是一个局部变量(值为4的那个),而不是(可能是现有的)全局变量。要解决此问题,请将baz强制转换为全局:

 def foo():
     def bar():
         global baz
         return baz + 1

这样它就不会尝试将名称解析为非本地版本的baz。更好的是,以一种看起来像局部变量的方式找到你正在使用re的位置(生成器表达式/列表推导是一个很好的检查位置),并将其命名为其他内容。

答案 2 :(得分:0)

其他解释是完美的,但让我添加我刚刚发现的另一个变体。由于Python 3比“物理”列表更喜欢迭代器,因此必须更加小心:

def foo():
    re = 3
    faulty = filter(lambda x: x%re, range(30))
    del re
    return faulty
list(foo())

仅在最后一行的return语句之后,尤其是在del re之后,才对过滤器表达式求值。因此,最后一行因错误而爆炸:

NameError: free variable 're' referenced before assignment in enclosing scope