Ответ 1
Настройка и тестирование
Чтобы проанализировать ваш вопрос, создайте две отдельные тестовые функции, которые реплицируют вашу проблему:
a=0
def test1():
print(a)
test1()
печатает 0
. Таким образом, вызов этой функции не проблематичен, а в следующей функции:
def test2():
print(a) # Error : local variable 'a' referenced before assignment
a=0
test2()
Мы получаем сообщение об ошибке:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test2
UnboundLocalError: local variable 'a' referenced before assignment
Демонтажные
Мы можем разобрать две функции (первая Python 2):
>>> import dis
>>> dis.dis(test1)
2 0 LOAD_GLOBAL 0 (a)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
И мы видим, что первая функция автоматически загружает глобальную a
, а вторая функция:
>>> dis.dis(test2)
2 0 LOAD_FAST 0 (a)
3 PRINT_ITEM
4 PRINT_NEWLINE
3 5 LOAD_CONST 1 (0)
8 STORE_FAST 0 (a)
11 LOAD_CONST 0 (None)
14 RETURN_VALUE
видя, что внутри него назначается a
, пытается выполнить LOAD_FAST из локальных сетей (в целях оптимизации, поскольку функции предварительно скомпилированы в байтовый код перед запуском.)
Если мы запустим это в Python 3, мы получим почти такой же эффект:
>>> test2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test2
UnboundLocalError: local variable 'a' referenced before assignment
>>>
>>> import dis
>>> dis.dis(test1)
2 0 LOAD_GLOBAL 0 (print)
3 LOAD_GLOBAL 1 (a)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> dis.dis() # disassembles the last stack trace
2 0 LOAD_GLOBAL 0 (print)
--> 3 LOAD_FAST 0 (a)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
3 10 LOAD_CONST 1 (0)
13 STORE_FAST 0 (a)
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
Мы снова видим ошибку на LOAD_FAST.