Функция locals() и ключевое слово self: инструменты доступа к переменным
Основное решение: использование 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}