赋值前引用的局部变量? [重复]

问题描述 投票:0回答:5

我正在使用 PyQt 库截取网页的屏幕截图,然后读取不同 URL 的 CSV 文件。我保留了一个可变提要,每次处理 URL 时都会增加,因此应该增加到 URL 的数量。

代码如下:

webpage = QWebPage()
fo = open("C:/Users/Romi/Desktop/result1.txt", "w")
feed = 0
def onLoadFinished(result):
    #fo.write( column1[feed])#, column2[feed], urls[feed])
   #feed = 0
   if not result:
        print "Request failed"
    fo.write(column1[feed])
    fo.write(',')
    fo.write(column2[feed])
    fo.write(',')
    #fo.write(urls[feed])
    fo.write(',')
    fo.write('404,image not created\n')
    feed = feed + 1
        sys.exit(1)
        save_page(webpage, outputs.pop(0))   # pop output name from list and save
   if urls:
        url = urls.pop(0)   # pop next url to fetch from list
        webpage.mainFrame().load(QUrl(url))
    fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n')
    fo.write(',')
    fo.write(column2[feed])
    fo.write(',')
    #fo.write(urls[feed])
    fo.write(',')
    fo.write('200,image created\n')
    feed = feed + 1
   else:
        app.quit()  # exit after last url

webpage.connect(webpage, SIGNAL("loadFinished(bool)"), onLoadFinished)
webpage.mainFrame().load(QUrl(urls.pop(0)))
#fo.close()
sys.exit(app.exec_())

它给了我错误:

local variable feed referenced before the assignment at fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n')

知道为什么吗?

python python-2.7 python-3.x variable-assignment
5个回答
124
投票

当 Python 解析函数定义的主体并遇到诸如

的赋值时
feed = ...

Python 默认将

feed
解释为局部变量。如果您不希望它成为局部变量,则必须将

global feed

在函数定义中。 global 语句不必位于函数定义的开头,但它通常位于此处。无论放在哪里,全局声明都让

feed
成为全局变量无处不在在函数中

没有global语句,由于

feed
被当作局部变量,当Python执行时

feed = feed + 1,

Python 首先评估右侧并尝试查找 feed 的值。第一次通过它发现

feed
是未定义的。因此错误。

修补代码的最短方法是在

global feed
的开头添加
onLoadFinished
。更好的方法是使用类:

class Page(object):
    def __init__(self):
        self.feed = 0
    def onLoadFinished(self, result):
        ...
        self.feed += 1

具有改变全局变量的函数的问题在于它使您的代码更难理解。函数不再是孤立的单元。它们的相互作用扩展到影响全局变量或受全局变量影响的所有事物。因此,它使更大的程序更难理解。

通过避免改变全局变量,从长远来看,您的代码将更容易理解、测试和维护。


45
投票

在你的函数顶部放置一个全局语句,你应该是好的:

def onLoadFinished(result):
    global feed
    ...

为了证明我的意思,请看这个小测试:

x = 0
def t():
    x += 1
t()

这与您完全相同的错误一起爆炸,其中:

x = 0
def t():
    global x
    x += 1
t()

没有。

之所以会这样,是因为在

t
内部,Python认为
x
是一个局部变量。此外,除非您明确告诉它
x
是全局的,否则它将尝试在
x
中使用名为
x += 1
的局部变量。但是,由于在
x
的本地范围内没有定义
t
,它会抛出一个错误。


12
投票

当 Python 解释器读取一个函数的定义(或者,我认为,甚至是一段缩进代码)时,函数内部分配给的所有变量都被添加到该函数的局部变量中。如果局部变量在赋值之前没有定义,Python 解释器不知道该做什么,所以会抛出这个错误。

这里的解决方法是添加

global feed

您的函数(通常靠近顶部)以向解释器表明 feed 变量不是该函数的本地变量。


2
投票

在我的案例中,完全相同的错误是由打字错误触发的! 我以为我的 var 名字是

varAlpha

但是在我定义的代码中

varalpha

& 得到错误

UnboundLocalError: local variable 'varAlpha' referenced before assignment

打电话时

varAlpha

我希望有一天它能帮助某人搜索那个错误并想知道(因为我对那个错误的搜索让我来到这里,同时与全局或非全局的使用无关,这是一个令人头疼的问题!)


0
投票

你可以对函数范围这样做

def main()

  self.x = 0

  def incr():
    self.x += 1
  
  for i in range(5):
     incr()
  
  print(self.x)
© www.soinside.com 2019 - 2024. All rights reserved.