Описанное ниже поведение списков в разных областях видимости часто сбивает с толку молодых разработчиков.
Рассмотрим следующий пример:
>>> lst = [1, 2, 3] >>> def foo1(): ... lst.append(5) # работает нормально ... ... >>> foo1() >>> lst # [1, 2, 3, 5] >>> lst = [1, 2, 3] >>> def foo2(): ... lst += [5] # выдает ошибку ... ... >>> foo2() # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # File "<stdin>", line 2, in foo # UnboundLocalError: local variable 'lst' referenced before assignment
Разбираемся почему вызов функции foo2()
выдает исключение, а foo1()
работает нормально?
Ответ более тонкий и кроется в области видимости глобальной переменной списка lst
в локальной области функции foo2()
.
Функция foo1()
не ПРИСВАИВАЕТ значение списку lst
, а просто расширяет его содержимое методом list.append()
, тогда как функция foo2()
пытается расширить список задействовав саму переменную lst
. Согласно правилам видимости переменных, в локальной области можно прочитать глобальную переменную, а при попытке присвоения, интерпретатор будет искать ее в локальной области функции, где она еще не определена и выдаст ошибку UnboundLocalError
.
Вторая конструкция lst + = [5]
(кстати, работает как .append()
без изменения id
списка) и является сокращением для lst = lst + [5]
, следовательно происходит присвоение значения списку lst
, которое в локальной области функции foo2()
определено еще не было.