赋值前引用的局部变量?
Posted
技术标签:
【中文标题】赋值前引用的局部变量?【英文标题】:Local variable referenced before assignment? 【发布时间】:2013-08-02 21:24:17 【问题描述】:我正在使用 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 variable scope error的可能重复 另一个可能的原因:我导入了 sys 模块两次。 【参考方案1】:当 Python 解析函数定义的主体,遇到诸如
之类的赋值时feed = ...
Python 默认将feed
解释为局部变量。如果你不希望它是一个局部变量,你必须把
global feed
在函数定义中。全局语句不必位于函数定义的开头,但通常放置在此处。无论放在哪里,全局声明都会使feed
成为函数中的全局变量everywhere。
没有全局语句,因为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
使用改变全局变量的函数的问题在于,它使你的代码更难理解。函数不再是孤立的单元。它们的相互作用延伸到影响或受全局变量影响的所有事物。因此,它使较大的程序更难理解。
通过避免改变全局变量,从长远来看,您的代码将更容易理解、测试和维护。
【讨论】:
你为什么不需要为dict做这个? @HoKy22:您是在问为什么dct[key] = val
不会引发“赋值前引用的局部变量”错误?原因是这不是 bare name 分配。相反,它会导致 Python 调用函数dct.__setitem__(key, val)
。
是的,这就是我要问的。例如,在一个文件中,一直在顶部,你只需输入 dict = 然后在一个方法中,你设置 dict['apple'] = 5 并在不同的方法中你可以 print(dict['apple '])。所以这是因为 dict 调用 __setitem__('apple', 5) 当你做 dict['apple'] = 5?
当 Python 在函数中遇到 dct['apple'] = 5
时,它不会将其视为对 dct
的赋值。它将其转换为函数调用dct.__setitem__('apple', 5)
。 (我试图避免调用变量dict
,因为它会影响同名的内置函数)。假设没有分配给dct
,dct
不是函数的局部变量。所以根据LEGB scoping rules,Python 会在全局命名空间中找到dct
,因为dct =
是在脚本顶部定义的。因此,不会引发错误。
您可能还会发现 Ned Batchelder 在 Facts and myths about Python names and values 上的文章对您有所帮助。它将阐明您在思考 Python 如何处理裸变量名及其与值的关系时所需的心智模型。【参考方案2】:
在你的函数顶部放一个全局语句,你应该很好:
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 += 1
中使用名为x
的局部变量。但是,由于在t
的本地范围内没有定义x
,因此会引发错误。
【讨论】:
【参考方案3】:当 Python 解释器读取函数的定义(或者,我认为,甚至是缩进代码块)时,函数内分配给的所有变量都将添加到该函数的局部变量中功能。如果局部变量在赋值之前没有定义,Python 解释器不知道该怎么做,所以会抛出这个错误。
这里的解决方法是添加
global feed
到您的函数(通常靠近顶部)以向解释器指示 feed 变量不是该函数的本地变量。
【讨论】:
【参考方案4】:在我的情况下,完全相同的错误是由错字触发的! 我以为我的 var 名称是
varAlpha
但在我定义的代码中
varalpha
&得到错误
UnboundLocalError: local variable 'varAlpha' referenced before assignment
拨打varAlpha
时
我希望有一天它可以帮助某人搜索该错误并想知道(因为我搜索该错误导致我来到这里,而与使用全局或非全局无关,这是一个令人头疼的问题!)
【讨论】:
【参考方案5】:你可以对函数范围这样做
def main()
self.x = 0
def incr():
self.x += 1
for i in range(5):
incr()
print(self.x)
【讨论】:
以上是关于赋值前引用的局部变量?的主要内容,如果未能解决你的问题,请参考以下文章