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

Python:NameError:free变量';re';在封闭范围中的赋值之前引用,python,Python,我在Python 3.3.1(win7)中遇到了一个奇怪的名称错误 守则: 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 opt

我在Python 3.3.1(win7)中遇到了一个奇怪的名称错误

守则:

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
回溯(最近一次呼叫最后一次):
文件“py3createtorrent.py”,第794行,在
系统出口(主(系统argv))
文件“py3createtorrent.py”,第561行,主目录
excluded_regexps |=为options.exclude_pattern_ci中的regexp设置(重新编译(regexp,re.I))
文件“py3createtorrent.py”,第561行,在
excluded_regexps |=为options.exclude_pattern_ci中的regexp设置(重新编译(regexp,re.I))
NameError:在封闭范围中赋值之前引用了自由变量“re”
请注意,发生错误的第561行是上述代码中的第二行。换句话说:
re
不是自由变量。它只是一个正则表达式模块,可以在第一行很好地引用它

在我看来,对
re.I
的引用似乎是导致问题的原因,但我看不出原因。

回溯中的“自由变量”表明这是封闭范围内的局部变量。大概是这样的:

 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
(生成器表达式/列表理解是检查的好地方)并将其命名为其他名称。

最有可能的情况是,您在第561行下面的某个点处(可能是无意中)分配给
re
,但在同一个函数中。这会再现您的错误:

import re

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

main()

其他的解释是完美的,但是让我添加另一个我刚刚发现的变体。由于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

如果从第561行删除
re.I
,错误是否会消失?我对此表示怀疑——这个问题很可能是由于你在问题中遗漏了什么。试着提供一个答案。@alexis你是对的。如果我删除
re.I
,错误不会消失。你是对的。我再次将re模块导入该行下方的某个位置(本地导入函数范围)。然而,我不明白为什么Python没有抱怨第一行…很高兴它工作了。如果您可以构造一个再现问题的最小示例,我们可以为您解释python语义。现在您确实没有提供足够的信息。下面是一个复制错误的脚本:Python在第13行(与第12行相反)抛出一个NameError。您的代码在第12行没有引发,因为iterable是空的;因此genexp主体没有运行。