Функция locals() и ключевое слово self: инструменты доступа к переменным

Раздел: Основы Python -> Встроенные функции Python

Основное решение: использование locals() для доступа к локальным переменным

Функция locals() возвращает словарь всех локальных переменных в текущей области видимости. Внутри метода класса в этом словаре всегда присутствует ключ self, если метод не является статическим или классовым. Это позволяет динамически получать значения переменных без явного обращения по именам.

def example(a, b):
    c = a + b
    print(locals())

example(10, 20)

Python locals self (locals и self в python)

{'a': 10, 'b': 20, 'c': 30}

Python round (функция round в python)

Основной сценарий — отладка, когда нужно быстро вывести все текущие переменные. Также locals() применяется при форматировании строк с помощью str.format(), передавая словарь через **locals().

Варианты использования и вопросы

Как получить все локальные переменные внутри функции?

Вызов locals() внутри функции возвращает словарь с её параметрами и внутренними переменными. Важно: словарь является копией, и его изменение не влияет на реальные переменные.

def show_locals(x):
    y = x * 2
    loc = locals()
    print(loc)
    loc['y'] = 100  # не изменяет y
    print(y)

show_locals(5)
{'x': 5, 'y': 10}
10

Как получить локальные переменные вне функции?

На уровне модуля locals() возвращает то же, что и globals(). Для получения глобальных переменных явно используют globals().

GLOBAL_VAR = 42
print(locals() is globals())  # True на уровне модуля
True

Как self связан с locals() в методе класса?

Внутри обычного метода экземпляра locals() содержит ключ self, который ссылается на текущий объект. Это удобно для динамического доступа к атрибутам объекта.

class MyClass:
    def __init__(self, value):
        self.value = value
    def show(self):
        print(locals()['self'].value)

obj = MyClass(10)
obj.show()
10

Как использовать locals() для форматирования строк?

Можно передать словарь locals() в метод format() с распаковкой, чтобы ссылаться на переменные по именам.

name = 'Alice'
age = 30
message = 'Имя: {name}, возраст: {age}'.format(**locals())
print(message)
Имя: Alice, возраст: 30

Типичные ошибки и проблемы

Попытка изменить locals(): словарь, возвращаемый locals(), не является живой ссылкой на пространство имён. Присваивание новому ключу не создаёт переменную, а изменение существующего не меняет реальную переменную.

def broken():
    x = 1
    locals()['x'] = 2
    print(x)
broken()
1

Путаница с globals(): на верхнем уровне модуля locals() и globals() ссылаются на один словарь, но внутри функции это разные объекты. Использование locals() для доступа к глобальным переменным внутри функции может привести к ошибке.

Изменение self через locals(): хотя self присутствует в locals(), попытка перезаписать его (например, locals()['self'] = something) не повлияет на реальную ссылку, так как self передаётся как локальная переменная, но не может быть перепривязана таким способом.

Расширенные примеры с пояснениями

Пример 1: динамический доступ к переменным внутри функции с условной логикой.

Пример
def dynamic_access(operation):
    a = 10
    b = 20
    if operation == 'sum':
        result = a + b
    elif operation == 'mul':
        result = a * b
    else:
        result = None
    # Получение словаря локальных переменных
    local_vars = locals()
    # Вывод только тех переменных, которые не являются None
    for k, v in local_vars.items():
        if v is not None:
            print(f'{k} = {v}')

dynamic_access('sum')
a = 10
b = 20
result = 30
operation = sum

Пример 2: использование self в статическом и классовом методах.

Пример
class Demo:
    @staticmethod
    def static_method():
        print('self отсутствует в locals():', 'self' in locals())
    @classmethod
    def class_method(cls):
        print('cls присутствует:', 'cls' in locals())
        print('self отсутствует:', 'self' in locals())
    def instance_method(self):
        print('self присутствует:', 'self' in locals())
        print('locals:', list(locals().keys()))

Demo.static_method()
Demo.class_method()
d = Demo()
d.instance_method()
self отсутствует в locals(): False
cls присутствует: True
self отсутствует: False
self присутствует: True
locals: ['self']

Пример 3: форматирование строк с помощью locals() и f-строк (сравнение).

Пример
def fstring_vs_format(first, last):
    full = f'{first} {last}'
    # Эквивалент с format и locals()
    full2 = '{first} {last}'.format(**locals())
    print(full, full2)

fstring_vs_format('Иван', 'Петров')
Иван Петров Иван Петров

Пример 4: отслеживание изменений переменных в рекурсивной функции.

Пример
def factorial(n):
    if n == 1:
        return 1
    prev = factorial(n - 1)
    loc = locals()
    print(f'n={n}, prev={prev}, loc keys: {list(loc.keys())}')
    return n * prev

factorial(3)
n=1, prev=1, loc keys: ['n', 'prev']
n=2, prev=1, loc keys: ['n', 'prev']
n=3, prev=2, loc keys: ['n', 'prev']

Пример 5: использование locals() внутри класса для генерации строкового представления объекта.

Пример
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __repr__(self):
        # Используем self для доступа к атрибутам
        return f'Person(name={self.name!r}, age={self.age})'

p = Person('Мария', 25)
print(p)
Person(name='Мария', age=25)

Пример 6: сравнение locals() и vars() (для объектов).

Пример
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(3, 4)
print('vars(p):', vars(p))
# Внутри метода __init__ locals() включает self, x, y
# vars(self) даёт словарь атрибутов экземпляра
vars(p): {'x': 3, 'y': 4}

locals и self в Python - comments

En
Python locals self (python)