Python 3 在全局声明之前使用的 SyntaxWarning 变量

Python 3 SyntaxWarning variable used prior to global declaration

我收到以下错误:

Warning (from warnings module):
File "C:\Python34\projectEuler\projectEuler.py", line 316
global primeSet, primeList, primeCap, primeRan
SyntaxWarning: name 'primeRan' is used prior to global declaration

对于代码:

primeSet = {2, 3}
primeList = [2, 3]
primeCap = 3
primeRan = False
def primeGen():
  if primeRan:
    primeList, primeCap = primeList, PrimeCap
    global primeSet
  else:
    global primeSet, primeList, primeCap, primeRan
    primeRan = True
  for i in primeList:
    yield i
  while(True):
    primeCap += 2
    m = int(primeCap**.5)
    yesPrime = True
    for p in primeList:
        if p > m: break
        if primeCap%p == 0:
            yesPrime = False
            break
    if yesPrime:
        primeSet.add(primeCap)
        primeList.append(primeCap)
        yield primeCap

变量在赋值之前不会被写入。而且代码似乎有效。 语法消息是误报,还是应该在读取之前声明全局? (而不是只在写入前声明)

代码:

def primeGen():
    global primeRan  
    if primeRan:
        primeList, primeMax = primeList, PrimeCap
        global primeSet
    else:
        global primeSet, primeList, primeCap
        primeRan = True

去掉 SyntaxWarning。但是对于一个只读不写的值做全局减速好像是错误的。

我应该忽略语法警报吗?

不,你不能忽略它,从 Python 3.6 开始,这个 will cease to be a SyntaxWarning and instead be updated to an error (SyntaxError)。所以你最好现在就修复它,否则它可能会在未来的版本中无法执行 (>= 3.6)。

请参阅 global statement 上的文档:

Names listed in a global statement must not be used in the same code block textually preceding that global statement.

如您所见,这不是在 运行 时生成的警告,它是在 Python 编译您的函数对象并注意到包含 global 语句时生成的已被发现为本地的名称 (primeRan)。

您应该在此处引用 primeRan 之前添加 global 语句 并对 primeList 执行相同的操作问题。

但是,对于 primeList,您可以偷偷摸摸地利用 global 必须 首先解析这一事实。简而言之,切换条件,以便 Python 为它解析 global 语句 赋值语句之前:

 def primeGen():
     global primeRan
     if not primeRan:
         global primeSet, primeList, primeCap
         primeRan = True
     else:
         primeList, primeMax = primeList, PrimeCap
     # rest as is

由于 global 是解析器的指令,这会产生相同的行为 w/o 警告。

当然,使用globals 并不是一个好的做法。老实说,我看不出你需要使用它们的任何理由,你总是更好(从概念的角度和执行速度的角度来看)放弃使用 globals 而是交流使用参数和 return 值的函数。