Получить доступ

Как работают области видимости в Python?

JuniorФункции
Ещё спрашивают так:
  • Что такое правило LEGB?
  • Чем отличаются global и nonlocal?
  • Откуда берётся UnboundLocalError?
Коротко

Имя ищется по цепочке LEGB: Local → Enclosing → Global → Built-in.

  • Присваивание внутри функции делает имя локальным для всей функции
  • global — писать в переменную модуля, nonlocal — в переменную объемлющей функции

А ещё Циклы и if своей области не создают — только функции, классы, модули, comprehension

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Когда Python встречает имя, он ищет его последовательно:

  1. Local — локальные имена текущей функции;
  2. Enclosing — локальные имена объемлющих функций (для вложенных);
  3. Global — имена модуля;
  4. Built-in — встроенные: len, print, Exception.

Важно, когда решается «локальное ли имя»: при компиляции функции. Если в теле функции где-либо есть присваивание имени, оно локальное во всей функции. Поэтому код ниже падает с UnboundLocalError: x += 1 — это присваивание, значит x локальная, а читается она до того, как получила значение.

global x говорит, что x — имя модуля; nonlocal x — что это имя ближайшей объемлющей функции. Злоупотреблять global не стоит: состояние лучше передавать явно.

Блоки if, for, while, with новой области не создают: переменная цикла доступна после цикла. А генераторы списков и выражения-генераторы (comprehension) имеют свою область — их переменная наружу не утекает.

Пример

x = 10

def broken():
    x += 1          # UnboundLocalError

def fixed():
    global x
    x += 1

for i in range(3):
    pass
print(i)            # 2 — цикл не создаёт область

[j for j in range(3)]
# print(j)          # NameError — у comprehension своя область

Что хотят услышать

  • Порядок поиска LEGB.
  • Правило «присваивание делает имя локальным» и UnboundLocalError.
  • Разница между global и nonlocal.
  • Что блоки не создают области видимости.

Частые ошибки

  • Думать, что if или for создают свою область, как в C или Java.
  • Объяснять UnboundLocalError «порядком строк», не упоминая правило присваивания.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем