Преобразовать имя переменной в строку?

Я хотел бы преобразовать имя переменной python в строковый эквивалент, как показано. Есть идеи как?

var = {}
print ???  # Would like to see 'var'
something_else = 3
print ???  # Would print 'something_else'

person Brandon Pelfrey    schedule 07.10.2009    source источник
comment
Не могли бы вы уточнить, чего вы пытаетесь достичь? Похоже, вы неправильно спрашиваете, как решить проблему. Кроме того, есть аналогичный вопрос, но о Ruby stackoverflow.com /questions/58482/ruby-get-a-имя-переменных   -  person dbr    schedule 08.10.2009
comment
Я проверил этот вопрос, потому что, используя RPy2, я хочу передать переменную Python с одноименным именем R. Бесполезный (но близкий к моему приложению) пример: def to_R( py_var ): r.assign( 'py_var', py_var ) чтобы присвоить данные в (Py) py_var среде R и иметь то же имя. Вместо этого мне было бы полезно сделать r.assign( py_var.stringof, py_var ) а-ля D, так как имя переменной передается моему fn to_r не обязательно py_var.   -  person Matthew Turner    schedule 26.01.2013
comment
Один из способов использовать это — когда оператор Assert терпит неудачу. Вы можете предоставить пользователю точное имя рассматриваемой переменной, сохраняя общий код, например. AssertionError: 'something_else' должно быть числом больше 5. Затем вы можете проверить каждую переменную, значение которой должно быть больше 5, и получить имя переменной в сообщении AssertionError.   -  person nu everest    schedule 15.05.2014


Ответы (19)


TL;DR: невозможно. См. «заключение» в конце.


Существует сценарий использования, в котором вам это может понадобиться. Я не имею в виду, что нет лучших способов или достижения той же функциональности.

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

Что было бы необходимо, так это обратная функция eval():

get_indentifier_name_missing_function()

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


Рассмотрим следующее текущее положение дел:

random_function(argument_data)

Если кто-то передает имя идентификатора («функция», «переменная», «словарь» и т. д.) argument_data в random_function() (другое имя идентификатора), он фактически передает идентификатор (например: <argument_data object at 0xb1ce10>) другому идентификатору (например: <function random_function at 0xafff78>) :

<function random_function at 0xafff78>(<argument_data object at 0xb1ce10>)

Насколько я понимаю, в функцию передается только адрес памяти:

<function at 0xafff78>(<object at 0xb1ce10>)

Следовательно, нужно было бы передать строку в качестве аргумента random_function(), чтобы эта функция имела имя идентификатора аргумента:

random_function('argument_data')

Внутри random_function()

def random_function(first_argument):

, можно было бы использовать уже предоставленную строку 'argument_data' для:

  1. служить «имя идентификатора» (для отображения, регистрации, разделения/объединения строк и т. д.)

  2. передать функцию eval(), чтобы получить ссылку на фактический идентификатор и, следовательно, ссылку на реальные данные:

    print("Currently working on", first_argument)
    some_internal_var = eval(first_argument)
    print("here comes the data: " + str(some_internal_var))
    

К сожалению, это работает не во всех случаях. Это работает только в том случае, если random_function() может преобразовать строку 'argument_data' в фактический идентификатор. т.е. Если имя идентификатора argument_data доступно в пространстве имен random_function().

Это не всегда так:

# main1.py
import some_module1

argument_data = 'my data'

some_module1.random_function('argument_data')


# some_module1.py
def random_function(first_argument):
    print("Currently working on", first_argument)
    some_internal_var = eval(first_argument)
    print("here comes the data: " + str(some_internal_var))
######

Ожидаемые результаты:

Currently working on: argument_data
here comes the data: my data

Поскольку имя идентификатора argument_data недоступно в пространстве имен random_function(), вместо этого будет получено:

Currently working on argument_data
Traceback (most recent call last):
  File "~/main1.py", line 6, in <module>
    some_module1.random_function('argument_data')
  File "~/some_module1.py", line 4, in random_function
    some_internal_var = eval(first_argument)
  File "<string>", line 1, in <module>
NameError: name 'argument_data' is not defined

Теперь рассмотрим гипотетическое использование get_indentifier_name_missing_function(), которое будет вести себя, как описано выше.

Вот фиктивный код Python 3.0: .

# main2.py
import some_module2
some_dictionary_1       = { 'definition_1':'text_1',
                            'definition_2':'text_2',
                            'etc':'etc.' }
some_other_dictionary_2 = { 'key_3':'value_3',
                            'key_4':'value_4', 
                            'etc':'etc.' }
#
# more such stuff
#
some_other_dictionary_n = { 'random_n':'random_n',
                            'etc':'etc.' }

for each_one_of_my_dictionaries in ( some_dictionary_1,
                                     some_other_dictionary_2,
                                     ...,
                                     some_other_dictionary_n ):
    some_module2.some_function(each_one_of_my_dictionaries)


# some_module2.py
def some_function(a_dictionary_object):
    for _key, _value in a_dictionary_object.items():
        print( get_indentifier_name_missing_function(a_dictionary_object)    +
               "    " +
               str(_key) +
               "  =  " +
               str(_value) )
######

Ожидаемые результаты:

some_dictionary_1    definition_1  =  text_1
some_dictionary_1    definition_2  =  text_2
some_dictionary_1    etc  =  etc.
some_other_dictionary_2    key_3  =  value_3
some_other_dictionary_2    key_4  =  value_4
some_other_dictionary_2    etc  =  etc.
......
......
......
some_other_dictionary_n    random_n  =  random_n
some_other_dictionary_n    etc  =  etc.

К сожалению, get_indentifier_name_missing_function() не увидит "исходные" имена идентификаторов (some_dictionary_,some_other_dictionary_2,some_other_dictionary_n). Он увидит только имя идентификатора a_dictionary_object.

Поэтому реальный результат скорее будет таким:

a_dictionary_object    definition_1  =  text_1
a_dictionary_object    definition_2  =  text_2
a_dictionary_object    etc  =  etc.
a_dictionary_object    key_3  =  value_3
a_dictionary_object    key_4  =  value_4
a_dictionary_object    etc  =  etc.
......
......
......
a_dictionary_object    random_n  =  random_n
a_dictionary_object    etc  =  etc.

Таким образом, обратная функция eval() в этом случае не будет так полезна.


В настоящее время нужно было бы сделать это:

# main2.py same as above, except:

    for each_one_of_my_dictionaries_names in ( 'some_dictionary_1',
                                               'some_other_dictionary_2',
                                               '...',
                                               'some_other_dictionary_n' ):
        some_module2.some_function( { each_one_of_my_dictionaries_names :
                                     eval(each_one_of_my_dictionaries_names) } )
    
    
    # some_module2.py
    def some_function(a_dictionary_name_object_container):
        for _dictionary_name, _dictionary_object in a_dictionary_name_object_container.items():
            for _key, _value in _dictionary_object.items():
                print( str(_dictionary_name) +
                       "    " +
                       str(_key) +
                       "  =  " +
                       str(_value) )
    ######

В заключении:

  • Python передает только адреса памяти в качестве аргументов функций.
  • Строки, представляющие имя идентификатора, могут быть возвращены к фактическому идентификатору функцией eval() только в том случае, если идентификатор имени доступен в текущем пространстве имен.
  • Гипотетическая обратная функция eval() не будет полезна в случаях, когда имя идентификатора не "видится" непосредственно вызывающим кодом. Например. внутри любой вызываемой функции.
  • Currently one needs to pass to a function:
    1. the string representing the identifier name
    2. фактический идентификатор (адрес памяти)

Этого можно добиться путем одновременной передачи 'string' и eval('string') в вызываемую функцию. Я думаю, что это самый «общий» способ решения этой проблемы с яйцом и курицей для произвольных функций, модулей, пространств имен, без использования краеугольных решений. Единственным недостатком является использование функции eval(), которая может легко привести к незащищенному коду. Необходимо соблюдать осторожность, чтобы не передавать в функцию eval() что угодно, особенно нефильтрованные внешние входные данные.

person Petru Zaharia    schedule 10.09.2010
comment
Это выдающаяся статья, и именно за таким высококачественным контентом я и прихожу сюда. - person Brendan; 06.06.2018
comment
В Python что-то не так, если для получения имени объекта нам нужен ответ на 5 страниц на StackOverflow. :/ - person Seymour; 09.02.2020
comment
TL; dr было бы неплохо. - person Nimitz14; 13.09.2020
comment
@ Nimitz14 Включено TL;DR. Не стесняйтесь предлагать правки, исправления. - person Petru Zaharia; 14.09.2020
comment
в TLDR говорится, что невозможно достичь того, о чем просила OP. Тем не менее, ответ @Alice и другие подобные ответы, в которых предлагается использование locals() или globals(), достигают именно этого. Так что этот TLDR вводит в заблуждение, и это не должно быть принятым ответом. - person Robyc; 10.11.2020
comment
@seymour Я написал функцию varname ниже, которая фактически отвечает на вопрос. imo: это недостающая функция в python. я объяснил почему. этот принятый ответ вводит в заблуждение. - person Erik Aronesty; 14.01.2021
comment
Есть ряд языков, которые обеспечивают эту функциональность - даже C/C++, скомпилированный в машинный язык, может через определения; Python может похвастаться простой в использовании точкой входа для программирования, но ему не хватает такого популярного инструмента, чтобы люди могли учиться и видеть, что делает их программа; Как и в C/C++, функция времени компиляции может отлично выполнять эту работу, но кажется, что все предлагаемые методы поиска имени переменной в globals() и т. д. успешны лишь частично и не могут работать в 100% случаев. Сопоставление выполняется для объектов, на которые могут ссылаться несколько переменных. - person Codemeister; 25.03.2021

Я искал этот вопрос, потому что хотел, чтобы программа Python печатала операторы присваивания для некоторых переменных в программе. Например, он может напечатать «foo = 3, bar = 21, baz = 432». Функции печати потребуются имена переменных в строковой форме. Я мог бы снабдить свой код строками "foo", "bar" и "baz", но это было похоже на повторение самого себя. Прочитав предыдущие ответы, я разработал решение ниже.

Функция globals() ведет себя как словарь с именами переменных (в виде строк) в качестве ключей. Я хотел получить из globals() ключ, соответствующий значению каждой переменной. Метод globals().items() возвращает список кортежей; в каждом кортеже первый элемент — это имя переменной (в виде строки), а второй — значение переменной. Моя функция variablename() просматривает этот список, чтобы найти имена переменных, которые соответствуют значению переменной, имя которой мне нужно в строковой форме.

Функция itertools.ifilter() выполняет поиск, проверяя каждый кортеж в списке globals().items() с помощью функции lambda x: var is globals()[x[0]]. В этой функции x — проверяемый кортеж; x[0] — это имя переменной (в виде строки), а x[1] — это значение. Лямбда-функция проверяет, совпадает ли значение проверяемой переменной со значением переменной, переданной в variablename(). Фактически, используя оператор is, лямбда-функция проверяет, связано ли имя тестируемой переменной с тем же самым объектом, что и переменная, переданная в variablename(). Если это так, кортеж проходит проверку и возвращается функцией ifilter().

Функция itertools.ifilter() фактически возвращает итератор, который не возвращает никаких результатов до тех пор, пока не будет вызван должным образом. Чтобы вызвать его правильно, я поместил его в понимание списка [tpl[0] for tpl ... globals().items())]. Понимание списка сохраняет только имя переменной tpl[0], игнорируя значение переменной. Создаваемый список содержит одно или несколько имен (в виде строк), связанных со значением переменной, переданной в функцию variablename().

В показанных ниже примерах использования variablename() требуемая строка возвращается как элемент списка. Во многих случаях это будет единственный элемент в списке. Однако, если другому имени переменной будет присвоено такое же значение, список будет длиннее.

>>> def variablename(var):
...     import itertools
...     return [tpl[0] for tpl in 
...     itertools.ifilter(lambda x: var is x[1], globals().items())]
... 
>>> var = {}
>>> variablename(var)
['var']
>>> something_else = 3
>>> variablename(something_else)
['something_else']
>>> yet_another = 3
>>> variablename(something_else)
['yet_another', 'something_else']
person Ken Manly    schedule 23.07.2011

пока это переменная, а не второй класс, у меня это работает:

def print_var_name(variable):
 for name in globals():
     if eval(name) == variable:
        print name
foo = 123
print_var_name(foo)
>>>foo

это происходит для членов класса:

class xyz:
     def __init__(self):
         pass
member = xyz()
print_var_name(member)
>>>member

и это для классов (например):

abc = xyz
print_var_name(abc)
>>>abc
>>>xyz

Итак, для классов он дает вам имя И свойства

person Alice    schedule 12.03.2013
comment
Пожалуйста, отредактируйте свой пост, чтобы избежать проблем с форматированием. Трудно понять, что вы говорите. - person yhw42; 12.03.2013
comment
Очень приятно читать пост, который отвечает на вопрос, не разглагольствуя о том, почему этот вопрос задают. - person user5920660; 30.08.2017
comment
Обратите внимание, что одно и то же значение может быть привязано к нескольким именам. В этом случае приведенный выше код напечатает несколько имен. Нет никакого способа узнать, какое имя является правильным. - person steveha; 12.11.2020
comment
используйте is variable, а не == variable... безопаснее - person Erik Aronesty; 14.01.2021
comment
К сожалению, это больше не работает в python 3. Замена print name на print(name) вполне очевидна, но все равно выдает ошибку. Исправление @Erik Aronesty заставляет его работать, но проблема, на которую указывает @steveha, все еще остается. - person JC_CL; 20.05.2021

Технически информация доступна для вас, но, как спрашивали другие, как бы вы использовали ее разумным образом?

>>> x = 52
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 
'x': 52, '__doc__': None, '__package__': None}

Это показывает, что имя переменной представлено в виде строки в словаре globals().

>>> globals().keys()[2]
'x'

В данном случае это третий ключ, но нет надежного способа узнать, где окажется заданное имя переменной.

>>> for k in globals().keys():
...   if not k.startswith("_"):
...     print k
...
x
>>>

Вы можете отфильтровать системные переменные таким образом, но вы все равно получите все свои собственные элементы. Просто запустив этот код выше, вы создали еще одну переменную «k», которая изменила положение «x» в словаре.

Но, возможно, это полезное начало для вас. Если вы сообщите нам, для чего вам нужна эта возможность, возможно, будет предоставлена ​​​​более полезная информация.

person Todd    schedule 07.10.2009
comment
Крис, ваш комментарий, похоже, не относится к моему ответу или первоначальному вопросу. Кого ты ругаешь и почему? Вы не знаете, пишет ли он производственный код или просто экспериментирует с функциями языка для собственного обучения. - person Todd; 08.10.2009

Это невозможно.

В Python действительно нет такой вещи, как «переменная». На самом деле у Python есть «имена», к которым могут быть привязаны объекты. Для объекта не имеет значения, с какими именами он может быть связан. Он может быть связан с десятками разных имен или ни с одним.

Рассмотрим этот пример:

foo = 1
bar = 1
baz = 1

Теперь предположим, что у вас есть целочисленный объект со значением 1, и вы хотите работать в обратном направлении и найти его имя. Что бы вы напечатали? Этот объект связан с тремя разными именами, и все они одинаково допустимы.

В Python имя — это способ доступа к объекту, поэтому напрямую работать с именами невозможно. Может быть какой-то умный способ взломать байт-коды Python или что-то еще, чтобы получить значение имени, но это в лучшем случае салонный трюк.

Если вы знаете, что хотите, чтобы print foo напечатало "foo", вы могли бы просто выполнить print "foo" в первую очередь.

РЕДАКТИРОВАТЬ: я немного изменил формулировку, чтобы сделать ее более понятной. Кроме того, вот еще лучший пример:

foo = 1
bar = foo
baz = foo

На практике Python повторно использует один и тот же объект для целых чисел с общими значениями, такими как 0 или 1, поэтому первый пример должен привязать один и тот же объект ко всем трем именам. Но этот пример кристально ясен: один и тот же объект привязан к foo, bar и baz.

person steveha    schedule 07.10.2009
comment
у объектов нет имен, у имен есть объекты - person John La Rooy; 08.10.2009
comment
Есть способ работать с этими именами, globals() dict, но неясно, как его использовать, чтобы делать то, что просил OP. - person Todd; 08.10.2009
comment
конечно, это возможно. и при этом довольно тривиальный (в любом случае это решает проблему ОП). это просто то, что никто не должен хотеть делать. - person SilentGhost; 08.10.2009
comment
вы говорите, что это невозможно. И все же возможно. Смотрите другие ответы. @SilentGhost: не могли бы вы пояснить, почему никто не должен хотеть этого делать? Я думаю, это зависит от приложения. Каков ваш аргумент? - person Robyc; 10.11.2020
comment
@Robyc Вы говорите, что все же возможно. Хорошо. Я привел примеры привязки foo bar и baz к 1. Тогда как зовут 1? Если вы просмотрите все глобальные переменные, вы можете вернуть список имен переменных: ['foo', 'bar', 'baz'] (в произвольном порядке). Хорошо. Какая польза от этого списка? Является ли одно из имен настоящим именем 1? (Нет.) Те из нас, кто говорит, что это невозможно, все согласны с тем, что вы можете просмотреть глобальные переменные и найти все имена; мы просто не думаем, что это полезно. Как я уже сказал, объект может быть связан с десятками разных имен или ни с одним. - person steveha; 11.11.2020
comment
@Robyc Вы также сказали, что я думаю, это зависит от приложения. Хорошо. Пожалуйста, приведите мне пример какого-нибудь случая, когда было бы полезно иметь возможность просматривать глобальные переменные и находить все имена переменных, к которым привязана данная ссылка на объект. Я не знаю ни одного, но если он у вас есть, мне очень интересно; пожалуйста, поделитесь им с нами. - person steveha; 11.11.2020
comment
Я определяю набор имен переменных (они могут указывать на одно и то же значение, это не имеет значения), которые используются для некоторой обработки. Затем я хочу сохранить результаты моей обработки, написав в имени файла имя переменной, которую я использовал для этого конкретного результата, чтобы отслеживать, что есть что. Например. var1=10 ==> result1 = some_processing(var1) ==> out_file_1 = 'some_result_using_var1.png'. Конечно, вы можете сделать это со словарем, например: var1 = {"var1" : 10} и, возможно, это более питонический способ сделать это. - person Robyc; 11.11.2020
comment
@Robyc Если вы работаете с кучей имен, определенно лучше всего сохранить список или словарь имен и использовать его для их повторного поиска, а не пытаться просматривать глобальные переменные в надежде восстановить имена. позже. - person steveha; 12.11.2020
comment
Согласованный. После того, как я попробовал метод globals(), стало очевидно, что наличие словаря — гораздо лучший способ достичь моей цели (как я уже говорил в своем предыдущем комментарии). Опять же, извините, если я придирчив, вы не должны писать, что это невозможно, если это на самом деле возможно, отсюда и моя критика. Вы можете написать, что это крайне не рекомендуется во всех случаях, которые я могу придумать :) - person Robyc; 13.11.2020
comment
@Robyc Первоначальный вопрос заключался в том, чтобы восстановить имя переменной. Это действительно невозможно: вы не можете начать со значения и найти имя. Вы можете просмотреть глобальные переменные и составить список всех имен, которые в настоящее время имеют это значение, привязанное к ним, и если в списке есть только одно имя, то я думаю, вы нашли это имя; но основная посылка вопроса была ошибочной, и я не думаю, что было неправильно пытаться просветить человека, задавшего вопрос, как все работает на самом деле. Значение может быть связано с десятками имен или ни с одним. - person steveha; 14.11.2020

Вот краткий вариант, который позволяет указать любой каталог. Проблема с использованием каталогов для поиска чего-либо заключается в том, что несколько переменных могут иметь одно и то же значение. Итак, этот код возвращает список возможных переменных.

def varname( var, dir=locals()):
  return [ key for key, val in dir.items() if id( val) == id( var)]
person ZevGriner    schedule 23.08.2017

Вы каким-то образом должны ссылаться на переменную, имя которой хотите напечатать. Так это будет выглядеть так:

print varname(something_else)

Такой функции нет, а если бы и была, то было бы как-то бессмысленно. Вы должны ввести something_else, поэтому вы можете просто ввести кавычки слева и справа от него, чтобы напечатать имя в виде строки:

print "something_else"
person sth    schedule 07.10.2009
comment
Это должен быть комментарий, а не ответ. - person Steve; 27.02.2020
comment
я создал функцию varname ниже. работает и для методов. - person Erik Aronesty; 14.01.2021
comment
Это не правильно. Я хочу проверить имя переменной в цикле! Итак, я не могу напечатать это, и это не бессмысленно! - person mah65; 03.04.2021

Чего вы пытаетесь достичь? Нет абсолютно никаких причин делать то, что вы описываете, и, вероятно, есть гораздо лучшее решение проблемы, которую вы пытаетесь решить.

Наиболее очевидная альтернатива тому, что вы запрашиваете, — это словарь. Например:

>>> my_data = {'var': 'something'}
>>> my_data['something_else'] = 'something'
>>> print my_data.keys()
['var', 'something_else']
>>> print my_data['var']
something

В основном как ... вызов, я реализовал желаемый результат. Не используйте этот код, пожалуйста!

#!/usr/bin/env python2.6
class NewLocals:
    """Please don't ever use this code.."""
    def __init__(self, initial_locals):
        self.prev_locals = list(initial_locals.keys())

    def show_new(self, new_locals):
        output = ", ".join(list(set(new_locals) - set(self.prev_locals)))
        self.prev_locals = list(new_locals.keys())
        return output
# Set up
eww = None
eww = NewLocals(locals())

# "Working" requested code

var = {}

print eww.show_new(locals())  # Outputs: var

something_else = 3
print eww.show_new(locals()) # Outputs: something_else

# Further testing

another_variable = 4
and_a_final_one = 5

print eww.show_new(locals()) # Outputs: another_variable, and_a_final_one
person dbr    schedule 08.10.2009
comment
Это довольно круто, но настолько автоматически, насколько мне бы хотелось. Спасибо за подсказку =] - person Brandon Pelfrey; 10.10.2009
comment
Нет абсолютно никакой причины делать то, что вы описываете - у нас здесь местная всезнающая сущность. На самом деле для этого есть несколько хороших вариантов использования. - person MatrixTheatrics; 06.11.2020

Разве Django не делает этого при создании имен полей?

http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names

Мне кажется разумным.

person Joe    schedule 02.03.2011
comment
Я думаю, что в моделях django поля являются атрибутами одного класса или экземпляра, получение имен атрибутов — это не то же самое, что преобразование имени переменной в строку. - person WeizhongTu; 30.12.2015

Я думаю, что это классное решение, и я полагаю, лучшее, что вы можете получить. Но видите ли вы какой-либо способ справиться с неоднозначными результатами, которые может вернуть ваша функция? Как показывает оператор is ведет себя неожиданно с целыми числами, низкие целые числа и строки одно и то же значение кэшируется python, так что ваша функция имени переменной может с высокой вероятностью получить неоднозначные результаты. В моем случае я хотел бы создать декоратор, который добавляет новую переменную в класс по имени переменной, которое я передаю:

def inject(klass, dependency):
klass.__dict__["__"+variablename(dependency)]=dependency

Но если ваш метод возвращает неоднозначные результаты, как я могу узнать имя добавленной переменной?

var any_var="myvarcontent"
var myvar="myvarcontent"
@inject(myvar)
class myclasss():
    def myclass_method(self):
        print self.__myvar    #I can not be sure, that this variable will be set...

Возможно, если я также проверю локальный список, я мог бы, по крайней мере, удалить переменную «зависимость» из списка, но это не будет надежным результатом.

person fonzy    schedule 07.11.2012

Используя оператор распаковки:

>>> def tostr(**kwargs):
    return kwargs

>>> var = {}
>>> something_else = 3
>>> tostr(var = var,something_else=something_else)
{'var' = {},'something_else'=3}
person restrepo    schedule 25.05.2020

Вполне возможно с пакетом python-varname (python3):

from varname import nameof

s = 'Hey!'

print (nameof(s))

Вывод:

s

Получить пакет здесь:

https://github.com/pwwang/python-varname

person Synthase    schedule 17.01.2021

Это будет работать для простых типов данных (str, int, float, list и т. д.).

>>> def my_print(var_str) : 
      print var_str+':', globals()[var_str]
>>> a = 5
>>> b = ['hello', ',world!']
>>> my_print('a')
a: 5
>>> my_print('b')
b: ['hello', ',world!']
person Hadsbjerg    schedule 28.06.2011

Это не очень Pythonesque, но мне было любопытно, и я нашел это решение. Вам нужно продублировать словарь globals, так как его размер изменится, как только вы определите новую переменную.

def var_to_name(var):
    # noinspection PyTypeChecker
    dict_vars = dict(globals().items())

    var_string = None

    for name in dict_vars.keys():
        if dict_vars[name] is var:
            var_string = name
            break

    return var_string


if __name__ == "__main__":
    test = 3
    print(f"test = {test}")
    print(f"variable name: {var_to_name(test)}")

который возвращает:

test = 3
variable name: test
person Frenmerican    schedule 11.09.2019
comment
Вы просматриваете словарь globals. Именно это было сделано в предыдущем ответе без создания дополнительных переменных и использования itertools. Хотя ответ хороший, я думаю, что, поскольку было предоставлено аналогичное решение, вы должны проголосовать за него и избежать повторения. - person razdi; 12.09.2019

Не знаю правильно это или нет, но мне помогло

def varname(variable):
    names = []
    for name in list(globals().keys()):
        string = f'id({name})'
        if id(variable) == eval(string):
            names.append(name)
    return names[0]  
person Hàm Nghi    schedule 16.07.2020

Чтобы получить имя переменной var в виде строки:

var = 1000
var_name = [k for k,v in locals().items() if v == var][0] 
print(var_name) # ---> outputs 'var'
person tamtam    schedule 29.07.2020

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

Кажется, это отсутствующая функция в python.

Существует ряд функций, таких как patch.object, которые принимают имя метода или свойства для исправления или доступа.

Учти это:

patch.object(obj, "method_name", new_reg)

Это потенциально может привести к ложному успеху при изменении имени метода. IE: вы можете отправить ошибку, вы думали, что тестируете.... просто из-за плохого рефакторинга имени метода.

Теперь рассмотрим: varname. Это может быть эффективная встроенная функция. Но пока он может работать, итерируя объект или фрейм вызывающего объекта:

Теперь ваш звонок может быть:

patch.member(obj, obj.method_name, new_reg)

И функция исправления может вызвать:

varname(var, obj=obj)

Это будет: утверждать, что переменная связана с объектом, и возвращать имя члена. Или, если объект не указан, используйте кадр стека вызывающих абонентов для его получения и т. д.

В какой-то момент его можно было бы сделать эффективным встроенным, но вот определение, которое работает. Я намеренно не поддерживал встроенные, которые легко добавить:

Не стесняйтесь вставлять это в пакет с именем varname.py и использовать его в ваших вызовах patch.object:

patch.object(obj, varname(obj, obj.method_name), new_reg)

Примечание: это было написано для Python 3.

import inspect

def _varname_dict(var, dct):
    key_name = None
    for key, val in dct.items():
        if val is var:
            if key_name is not None:
                raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
            key_name = key
    return key_name

def _varname_obj(var, obj):
    key_name = None
    for key in dir(obj):
        val = getattr(obj, key)
        equal = val is var
        if equal:
            if key_name is not None:
                raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
            key_name = key
    return key_name

def varname(var, obj=None):
    if obj is None:
        if hasattr(var, "__self__"):
            return var.__name__
        caller_frame = inspect.currentframe().f_back
        try:
            ret = _varname_dict(var, caller_frame.f_locals)
        except NameError:
            ret = _varname_dict(var, caller_frame.f_globals)
    else:
        ret = _varname_obj(var, obj)
    if ret is None:
        raise NameError("Name not found. (Note: builtins not supported)")
    return ret
person Erik Aronesty    schedule 14.01.2021

Этот модуль работает для преобразования имен переменных в строку: https://pypi.org/project/varname/

Используйте это так:

из varname импортировать nameof

переменная=0

имя = имя (переменная)

печать (имя)

// вывод: переменная

Установите его:

pip установить имя_переменной

person Gabriel Ceron Viveros    schedule 03.06.2021
comment
Этот пакет уже упоминался здесь. (Кстати: ! неверно перед pip). - person Sven Eberth; 04.06.2021
comment
Я заметил, что это уже упоминалось после публикации. Вы правы насчет «!», я его отредактировал. Было так, потому что я был на ноутбуке, используйте «!», только если вы находитесь на Jupyter. - person Gabriel Ceron Viveros; 06.06.2021

print "var"
print "something_else"

Или вы имели в виду что-то_еще?

person Jonathan Feinberg    schedule 07.10.2009