2016-01-29 3 views
0

Если вы столкнулись с какой-то странной проблемой в моей программе. Если упростили мой код на следующее:странная проблема в python: UnboundLocalError: локальная переменная 'y', на которую ссылаются до назначения

def x(y="test"): 
    def xx(): 
     if False: 
      y = "blubb" 
     print y 
    xx() 
    print y 

x() 

Это бросает UnboundLocalError: обращаться до Ошибки присваивания.

Если я исправить код на следующее:

def x(y="test"): 
    def xx(): 
     print y 
    xx() 
    print y 

x() 

Мой код работает снова. Я на Python 2.7. Я просто понял, что последующее исправление работы, а также и это, как я собираюсь исправить свое программное обеспечение на данный момент: функция

def x(y="test"): 
    def xx(): 
     _y = y 
     if False: 
      _y = "blubb" 
     print _y 
    xx() 
    print y 

x() 
+1

Назначение 'y' из' 'xx' делает' y' в 'xx' локальным' xx', поэтому оно больше не ищет для него уровня вверх. В Python 3 есть декларация 'nonlocal', которая позволит' xx' изменять 'y' в родительской области, но я не думаю, что вы можете что-то сделать в Python 2. –

ответ

0

Y-переменная, созданная во внутреннем хх() в оператор 'if' переопределяет внешнюю переменную y. Поэтому, когда вы вызываете print y внутри xx(), это относится к локальной переменной y, которая не назначена.

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

+0

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

+0

Да, внутри xx() интерпретатор видит локальную область переменной y, которая имеет приоритет над внешним y. – sean

1

Проверьте правило LEGB в this answer для получения общего ответа.

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

В вашем втором примере y не является локальной переменной, поэтому по правилу LEGB переменная y находится в ее родительской функции, и все работает.

Последний пример работает, потому что вы используете локальную переменную _y, которая всегда назначается.