Найти в Дзене
Python Django

Как узнать имя переменной?

Как узнать имя переменной?

Какой-то из каналов про Python писал, что это невозможно узнать имя переменной, которой мы что-то присвоили. Это не совсем так. Представляю вам функцию, которая вернет все имена, ассоциированные с переданным ей объектом. Она использует модуль inspect, который позволяет узнать о загруженном в Python коде все, что можно только придумать, в том числе и имена переменных:

def find_names(obj):

import inspect

# currentframe - текущий контекст выполнения, т.е. эта же функция

# а f_back - фрейм код, который ее вызвал

parent_frame = inspect.currentframe().f_back

# соберем все глобальные и локальные переменные вызывающего кода

# это словарь имя переменной: ее значение

search = {**parent_frame.f_globals, **parent_frame.f_locals}

for name, v in search.items():

# если переменная ЯВЛЯЕТСЯ искомым объектом вернем ее имя

if v is obj:

yield name

Тестируем:

class A: ...

x = A()

y = x

print(list(find_names(x))) # ['x', 'y']

Так как имен может быть несколько, то возвращается список. Кроме того, может быть ситуация, когда в список запрячутся посторонние имена. Например, на None могут ссылаться встроенные переменные интерпретатора:

a = None

print(list(find_names(a)))

# ['__doc__', '__package__', '__spec__', '__cached__', 'a']

Зачем это вообще нужно? Например, можно сделать функцию, что будет составлять словарь из переменных по их именам:

def make_dict(*args):

return {next(find_names(_arg)): _arg for _arg in args}

a, b, c = 10, 20, 30

d = make_dict(a, b, c)

print(d) # {'a': 10, 'b': 20, 'c': 30}

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

#хаки #секреты

Наука
7 млн интересуются