【问题标题】:Python 3 SyntaxWarning variable used prior to global declaration全局声明之前使用的 Python 3 SyntaxWarning 变量
【发布时间】:2017-05-16 21:51:49
【问题描述】:

我收到以下错误:

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。但是对一个只被读取而不是写入的值进行全局减速似乎是错误的。

我应该忽略语法警报吗?

【问题讨论】:

  • 因为你的变量是不可变的,所以你需要添加global,否则python会在分配时创建另一个本地引用,并且逻辑上在访问它时会查找本地引用。
  • @Jean-FrançoisFabre 我的问题不是关于天气或全球减速是否必要。虽然我很高兴你引起了我的注意,因为它提供了丰富的信息。我提供的示例是一段复杂的代码,此后我通过包括删除外部引用在内的简化进行了改进(相对于计算时间)。我的问题是关于警告本身。答案比我想象的更相关。我不知道未来的版本会停止执行代码。我发现吉姆的回答很有启发性。其他人也可以。
  • @Jean-FrançoisFabre,作为旁注,外部列表将被改变天气或没有被声明为全局,程序未能按预期运行(将外部写入限制为发电机)。这是我从另一篇回答不同问题的帖子中得到的启示。

标签: python python-3.x syntax-error


【解决方案1】:

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

请参阅global statement 上的文档:

global 语句中列出的名称不得用于该全局语句之前的同一代码块中。

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

您应该在此处引用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 是解析器的指令,因此会产生相同的行为而没有警告。

当然,使用globals 不是一个好习惯。老实说,我看不出你为什么需要使用它们的任何理由,你总是最好(从概念的角度和执行速度的角度来看)放弃globals 的使用,而是与你的使用参数和返回值的函数。

【讨论】:

  • 我在 Python 3.6 上试过了,和你说的一样。你改变 if 语句顺序的想法奏效了。
猜你喜欢
  • 2017-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-30
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
  • 2015-05-11
相关资源
最近更新 更多