Что случилось и почему? Основываясь на области видимости переменной, вы ожидаете, что переменная будет найдена во внешней области (если она не определена), и она действительно работает, попробуйте это:
def o(n):
def i():
print("now in inner", n)
print("passed to outer", n)
i()
o(42)
Теперь, если вы определяете переменную с тем же именем в внутренняя область, она будет (в этой области) скрывать переменную во внешней области, вы можете присвоить ей любое значение, вы можете получить к ней доступ, все это происходит с помощью ее области действия:
def o(n):
def i():
n = "in"
print("now in inner", n)
print("passed to outer", n)
i()
print("back in outer", n)
o(42)
Так почему Вы видели UnboundLocalError
исключение? Поскольку python будет рассматривать любую локальную переменную для своей области, если она назначена в этой области, если на нее ссылаются до такого назначения, вместо этого к ней не будет обращаться во внешней области, но считается, что она еще не назначена локально:
def o(n):
def i():
print("now in inner", n)
n = "in"
print("passed to outer", n)
i()
print("back in outer", n)
o(42)
Если вы добавите оператор nonlocal
, как предложено в комментариях, ошибка исчезнет, поскольку переменная обращается к объему, а не считается локальной, однако это также означает, что любая изменения / (повторные) назначения также влияют на внешнюю область видимости, и это (особенно в более крупной программе) может вызывать удивление и сбивать с толку:
def o(n):
def i():
nonlocal n
print("now in inner", n)
n = "in"
print("passed to outer", n)
i()
print("back in outer", n)
o(42)
Чтобы сблизить связанные биты и явные отношения, это может было бы лучше передать значение переменной во внутреннюю функцию, выполнить любой лог c, который он должен выполнить, и заставить его вернуть результат:
def o(n):
def i(inner_n):
print("now in inner", n)
inner_n += 1
return inner_n
print("passed to outer", n)
print("i() returned", i(n))
print("back in outer", n)
o(42)
Чтобы указать на документацию :
Следующие конструкции связывают имена: ... цели, которые являются идентификаторами, если встречаются в назначении t ...
Если имя связано в блоке, оно является локальной переменной этого блока, если не объявлено как nonlocal
или global
.
Или как При этом присваивание может быть последним действием в этом блоке, но это означает, что переменная рассматривается как локальная на всем протяжении (если явно не указано иное).