Ответ
Хотя эти понятия тесно связаны, они описывают разные аспекты работы с переменными.
-
Пространство имен (Namespace) — это структура данных, которая хранит имена (переменные, функции) и связывает их с объектами. По сути, это словарь
{'имя': объект}. В Python существует несколько пространств имен: встроенное (built-in), глобальное, локальное. -
Область видимости (Scope) — это текстовая область в коде, из которой можно напрямую получить доступ к именам из определенного пространства имен. Она определяет правила, по которым Python ищет переменную в разных пространствах имен.
Ключевое правило поиска — LEGB (Local → Enclosing → Global → Built-in):
- L (Local) — локальная область внутри функции.
- E (Enclosing) — область видимости внешней функции (для вложенных функций).
- G (Global) — глобальная область модуля.
- B (Built-in) — встроенные имена Python (
print,lenи т.д.).
Пример:
x = 'global_x' # Имя 'x' в глобальном пространстве имен
def outer_func():
y = 'enclosing_y' # Имя 'y' в локальном пространстве имен outer_func
def inner_func():
z = 'local_z' # Имя 'z' в локальном пространстве имен inner_func
print(x) # Найдено в Global (G)
print(y) # Найдено в Enclosing (E)
print(z) # Найдено в Local (L)
inner_func()
outer_func()
# print(z) # Ошибка! NameError: name 'z' is not defined в глобальной области видимости
Итог:
- Пространство имен — это «что» (хранилище имен).
- Область видимости — это «где» (правила доступа к этому хранилищу).
Ответ 18+ 🔞
Давай разжую эту тему так, чтобы даже твоя бабушка, если бы вдруг решила в Python податься, всё поняла. Представь, что пространство имён — это такой большой, блядь, шкаф с ящиками. В каждом ящике лежат бумажки с надписями: «х», «у», «моя_переменная», «функция_которая_ничего_не_делает». На бумажке написано имя, а на обратной стороне — адрес, где в памяти этот объект живёт, типа «а вот тебе, сука, сам объект».
Так вот, пространство имён (namespace) — это и есть сам этот ящик, контейнер, словарь, где хранятся пары «имя → объект». Их несколько видов: встроенный ящик (там print, len лежат), глобальный (для всего модуля) и локальные (внутри каждой функции свои).
А теперь область видимости (scope) — это, сука, невидимые правила твоего дома. Они тебе говорят: «Слушай сюда, дружок-пирожок. Из кухни (локальная область) ты можешь лезть в холодильник на кухне (локальный namespace), а также в общий шкаф в прихожей (глобальный namespace), и даже в кладовку со старым хламом (встроенный namespace). Но из прихожей (глобальная область) тебе, мудак, на кухню в личные ящики лезть НИЗЗЯ!».
Вот эти правила поиска — и есть LEGB, священная мантра питониста:
- L (Local) — ищем на кухне, в своих тапках.
- E (Enclosing) — если не нашли, смотрим в коридоре за стенкой (если функция вложенная).
- G (Global) — если и там нет, идём в общий зал, ко всем.
- B (Built-in) — ну а если совсем всё хуёво, лезем в фундамент дома, там всегда
True,Falseи прочая хуйня валяется.
Смотри, как это в коде выглядит, ёпта:
x = 'global_x' # Бросил бумажку "x" в общий ящик в зале (глобальный namespace)
def outer_func():
y = 'enclosing_y' # Бросил бумажку "y" в ящик в коридоре (локальный namespace outer_func)
def inner_func():
z = 'local_z' # Бросил бумажку "z" в ящик на кухне (локальный namespace inner_func)
print(x) # Ищешь "x". На кухне нет (L). В коридоре нет (E). В зале — ОПА! Нашёл! (G)
print(y) # Ищешь "y". На кухне нет (L). В коридоре — О, ёба, вот же! (E)
print(z) # Ищешь "z". На кухне — да тут он, блядь, в первом ящике! (L)
inner_func()
outer_func()
# print(z) # А вот тут, друг мой, пиздец. Ты в зале (глобальная область), а пытаешься найти "z",
# который лежит только на кухне (в локальной области inner_func). NameError, пидорас!
Итог, коротко и на пальцах:
- Пространство имён — это ЧТО (ящик с бумажками-ссылками).
- Область видимости — это ГДЕ и ПО КАКИМ ПРАВИЛАМ тебе разрешено в эти ящики лазить.
Всё, теперь иди, попробуй, а то сидишь, блядь, теорию читаешь, а на практике потом UnboundLocalError ловишь, как мудак.