2013-08-01 2 views
24

Я использую библиотеку PyQt, чтобы сделать снимок экрана с веб-страницы, а затем прочитать файл CSV с разными URL-адресами. Я сохраняю переменную подачу, которая увеличивается каждый раз, когда URL-адрес обрабатывается и поэтому должен увеличиваться до количества URL-адресов.Локальная переменная, привязанная до назначения в Python?

Вот код:

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') 

Любая идея, почему?

+1

Возможный дубликат [Ошибка области переменной Python] (https://stackoverflow.com/questions/370357/python-variable-scope-error) – Nae

ответ

49

Когда Python разбирает тело определения функции и встречает назначение таких как

feed = ... 

Python интерпретирует feed как локальная переменная по умолчанию. Если вы не хотите, чтобы это была локальная переменная, вы должны поставить

global feed 

в определении функции. Глобальный оператор не должен быть в начале определения функции, но обычно он помещается. Где бы он ни находился, глобальная декларация делает feed глобальной переменной всюду в функции.

Без глобального утверждения, поскольку feed берется локальная переменная, когда Python выполняет

feed = feed + 1, 

Python оценивает правую первый и пытается найти значение корма. Первый раз через это находит feed не определено. Отсюда и ошибка.

Самый короткий способ исправить код - добавить global feed в начало onLoadFinished. Лучше всего использовать класс:

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

проблема с наличием функций, которые мутируют глобальные переменные в том, что она делает его труднее обращал внимания на свой код. Функции больше не изолированы. Их взаимодействие распространяется на все, что влияет или зависит от глобальной переменной. Таким образом, это делает более сложные программы более трудными для понимания.

Избегая мутирующих глобальных переменных, в конечном итоге ваш код будет легче понять, протестировать и поддерживать.

+0

Как вам не нужно это делать для dict? – HoKy22

+0

@ HoKy22: Вы спрашиваете, почему 'dct [key] = val' не вызывает ошибку« local variable referired before assign »? Причина в том, что это не задание * bare name *. Вместо этого он заставляет Python выполнять вызов функции 'dct .__ setitem __ (key, val)'. – unutbu

+0

да, вот что я прошу. например, в файле, все в верхней части, вы просто помещаете dict = {}, а затем в методе вы устанавливаете dict ['apple'] = 5 и другим способом вы можете печатать (dict ['apple «]). так что это потому, что dict call __setitem __ («apple», 5), когда вы делаете dict ['apple'] = 5? – HoKy22

20

Помещенный глобальное заявление в верхней части вашей функции, и вы должны быть хорошо:

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. Но, поскольку в локальной области t нет x, это вызывает ошибку.

5

Как интерпретатор Python считывает определение функции (или, я думаю, даже блок с отступом), все переменные, которые являются , назначенные внутри функции, добавляются к локалям этой функции. Если локаль не имеет определения перед назначением, интерпретатор Python не знает, что делать, поэтому он выдает эту ошибку.

Решение здесь, чтобы добавить

global feed 

вашей функции (обычно около вершины), чтобы указать интерпретатору, что переменная подача не является локальным для этой функции.

Смежные вопросы