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

kjl*_*kjl 3 python syntax-error python-3.x

我收到以下错误:

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
Run Code Online (Sandbox Code Playgroud)

对于代码:

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
Run Code Online (Sandbox Code Playgroud)

在分配变量之前,不会写入变量.代码似乎有效.语法消息是错误警报,还是应该在读取之前声明全局?(而不是仅在写入之前声明)

代码:

def primeGen():
    global primeRan  
    if primeRan:
        primeList, primeMax = primeList, PrimeCap
        global primeSet
    else:
        global primeSet, primeList, primeCap
        primeRan = True
Run Code Online (Sandbox Code Playgroud)

摆脱了SyntaxWarning.但是,对于只读取而不是写入的值,全局减速似乎是错误的.

我应该忽略语法警报吗?

Jim*_*ard 6

不,你不能忽视它,并且,从Python开始,3.6这将不再是一个SyntaxWarning,而是更新为错误(SyntaxError).因此,您现在可以更好地解决它,或者面对它未来未在版本中执行的前景(>= 3.6).

请参阅global声明中的文档:

global声明中列出的名称不得在该全局语句之前的文本上使用相同的代码块.

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

您应该添加global引用之前声明primeRan在这里也做同样为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
Run Code Online (Sandbox Code Playgroud)

由于global是解析器的指令,因此产生与警告无关的相同行为.

当然,使用globals不是一个好习惯.我看不出有什么理由要求你使用它们来说实话,你总是会更好(从概念的角度和执行速度明智)来减少使用globals并使用参数与你的函数进行通信并返回值.