Локальная переменная, на которую ссылаются перед назначением в Python?

Я использую библиотеку PyQt, чтобы сделать снимок экрана веб-страницы, а затем прочитать CSV-файл с разными URL-адресами. Я сохраняю переменный канал, который увеличивается каждый раз, когда обрабатывается 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 createdn')
    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 createdn')
    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')

есть идеи, почему?

3 ответов


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

feed = ...

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

global feed

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

без глобального заявления, так как 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

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

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


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

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, он выдает ошибку.


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

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

global feed

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