← Назад к вопросам

В чем разница между пространством имен и областью видимости?

2.0 Middle🔥 91 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между пространством имён и областью видимости

Это фундаментальные концепции в Python, которые часто путают, но они решают разные проблемы. Пространство имён (namespace) и область видимости (scope) работают вместе, но это не одно и то же.

Определение

Пространство имён (Namespace) — это словарь (dictionary), который хранит маппинг имён на объекты. Это структура данных.

Область видимости (Scope) — это правило, определяющее, из каких пространств имён можно получить доступ к переменной. Это правило доступности.

Наглядная разница

# Пространство имён - это конкретный словарь
print(globals())  # Глобальное пространство имён - обычный dict
# {__name__: __main__, __file__: ..., ...}

print(locals())   # Локальное пространство имён
# Тоже словарь с локальными переменными

# Область видимости - это правило доступа
def example():
    x = 10  # x находится в локальном пространстве имён
           # но его ВИДИМОСТЬ ограничена этой функцией
    print(x)  # Хорошо - x видна в своём scope

print(x)  # ЭрРОР! - x находится в пространстве имён функции,
          # но её видимость не распространяется на глобальный scope

Простое объяснение

Пространство имён = ящик с переменными
Область видимости = правило, кому доступен этот ящик

Переменная СУЩЕСТВУЕТ в пространстве имён, но видна только в определённой области видимости.

Типы пространств имён в Python

Python управляет несколькими пространствами имён одновременно:

# 1. Встроенное пространство имён (built-in)
print(dir(__builtins__))  # list, dict, len, print, etc.
len([1, 2, 3])  # Эта функция из встроенного пространства имён

# 2. Глобальное пространство имён (global)
x = 10  # Переменная в глобальном пространстве
y = 20

# 3. Локальное пространство имён (local)
def my_function():
    z = 30  # z существует в локальном пространстве функции
    print(z)  # Видна в локальной области видимости

my_function()
print(z)  # ERROR - z не видна в глобальной области видимости

Правило LEGB (порядок поиска переменных)

По правилу LEGB Python ищет переменную в следующем порядке:

Local → Enclosing → Global → Built-in

builtin_var = "встроенный"  # B - built-in (на самом деле глобальный в этом примере)
global_var = "глобальный"    # G - global

def outer():
    enclosing_var = "внешней функции"  # E - enclosing
    
    def inner():
        local_var = "локальный"  # L - local
        
        # Сейчас inner может видеть ВСЕ переменные благодаря LEGB:
        print(local_var)      # L - находится в локальном пространстве
        print(enclosing_var)  # E - находится в enclosing пространстве
        print(global_var)     # G - находится в глобальном пространстве
        print(len)            # B - встроенная функция
    
    inner()

outer()

Конкретные примеры

Пример 1: Локальное пространство имён

def function_a():
    x = "функция a"  # x существует в локальном пространстве функции_a

def function_b():
    x = "функция b"  # ДРУГОЙ x в отдельном локальном пространстве
    
# Оба x существуют в своих пространствах имён
# Но видны только внутри своих функций (область видимости)
function_a()  # Использует свой x
function_b()  # Использует свой x
print(x)      # ERROR - нет x в глобальной области видимости

Пример 2: Замыкание (closure)

def make_multiplier(multiplier):
    # multiplier в пространстве имён функции make_multiplier
    
    def inner(x):
        # inner может видеть multiplier благодаря enclosing scope
        return x * multiplier
    
    return inner

times_3 = make_multiplier(3)  # Создаём замыкание с multiplier=3
times_5 = make_multiplier(5)  # Другое замыкание с multiplier=5

print(times_3(10))  # 30 - используется multiplier=3 из enclosing scope
print(times_5(10))  # 50 - используется multiplier=5 из enclosing scope

# Каждое замыкание имеет СВОЁ пространство имён (разные multiplier)
# но ОДНа область видимости (всегда видна переменная)

Пример 3: global и nonlocal

counter = 0  # Глобальное пространство имён

def increment():
    global counter  # Показываем, что хотим использовать глобальную переменную
    counter += 1

increment()
print(counter)  # 1

# БЕЗ global попытаемся изменить:
def bad_increment():
    counter += 1  # ERROR: UnboundLocalError
    # Python думает, что counter - локальная переменная
    # но она не инициализирована перед использованием
# nonlocal для enclosing scope
def outer():
    x = 10
    
    def inner():
        nonlocal x  # Показываем, что используем x из enclosing scope
        x += 5
    
    inner()
    print(x)  # 15

outer()

Таблица сравнения

АспектПространство имёнОбласть видимости
Что этоСловарь имён → объектыПравило доступности
Как проверитьlocals(), globals(), vars()Попытаться использовать переменную
КоличествоНесколько одновременноОдна для переменной
ИзменяемостьМожно изменять прямо через dictОпределяется синтаксисом
Пример{x: 10, y: 20}local, enclosing, global

Практический пример для интервью

# Класс показывает работу с пространствами имён
class Counter:
    instances = 0  # Пространство имён класса
    
    def __init__(self, name):
        self.name = name  # Пространство имён объекта
        Counter.instances += 1
    
    def increment(self):
        local_count = 0  # Локальное пространство имён метода
        for i in range(10):
            local_count += 1
        return local_count

c1 = Counter("counter1")
c2 = Counter("counter2")

print(c1.name)           # Видна через объект
print(Counter.instances) # Видна через класс
print(c1.increment())    # 10

Итоговый совет

Запомни различие:

  • Пространство имён — это ХРАНИЛИЩЕ (где лежит переменная)
  • Область видимости — это ПРАВИЛО ДОСТУПА (кто может её взять)

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