Более простой способ создать словарь отдельных переменных?


220

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

>>> print(my_var.__name__)
'my_var'

Я хочу сделать это, потому что у меня есть куча переменных, которые я хотел бы превратить в словарь, например:

bar = True
foo = False
>>> my_dict = dict(bar=bar, foo=foo)
>>> print my_dict 
{'foo': False, 'bar': True}

Но я бы хотел что-то более автоматическое, чем это.

Python есть locals()и vars(), так что я думаю, что есть способ.


31
Так как люди, похоже, не понимают, о чем просят, я повторю здесь, потому что это интересный вопрос. Для данного массива [foo, bar, baz] вам нужен словарь типа {'foo': foo, 'bar': bar, 'baz': baz}, и вы не знаете, какие переменные находятся в массиве. поэтому спрашивающий спрашивает, как получить имя переменной в виде строки в Python. Теперь, надеюсь, люди смогут просмотреть ужасные ответы, чтобы найти несколько мест, где вы узнаете, почему это не очень хорошая идея в python.
Джесси Шерлок

3
Возможный дубликат: stackoverflow.com/questions/544919/…
Андерсон Грин

2
Одним из применений этой техники будет упрощение вызовов форматирования строк: '{var} {foo} {bar}'. Format (** named (var, foo, bar)), где "named" - это функция, которая возвращает dict ( 'var': var) как описано.
Гордон Бин

4
Я думаю, что это на самом деле плохой вопрос, потому что имена сопоставляются с объектами, у вас может быть несколько имен, указывающих на один и тот же объект, и я никогда не видел необходимости выполнять задачу инвертирования этого отображения. Поэтому тот факт, что здесь принят неправильный ответ, не имеет смысла - если поиск в Google привел вас сюда, вы явно задаете неправильный вопрос.
Аарон Холл

1
Это отличная идея для отладки!
Джон Ктехик

Ответы:


48

Вы пытаетесь это сделать?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

пример

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}

1
rlotun ближе к первоначальному «духу» этого, поскольку он позволяет обнаружить имя. Я мог бы использовать как ваш ответ. Или, может быть, просто используйте мою чертову руку, чтобы напечатать. Некоторые вещи просто не созданы для того, чтобы быть автоматизированными ...
e-sat

7
@ e-Satin: Чтобы @ rlotun's работал, вы должны предоставить список переменных. Если у вас есть список переменных, какой смысл «открывать» их имена?
S.Lott

4
Почему eval вместо того, чтобы явно использовать localals и globals?

1
@ Роджер Пэйт: Потому что я не мог понять, в чем смысл всего упражнения.
С.Лотт

242
Этот ответ не отвечает на заданный вопрос. Если у вас есть список переменных, какой смысл «открывать» их имена? Чтобы избежать дублирования, чтобы вместо print('x: ' + x)одного можно было писать magic_print(x)и иметь один и тот же вывод без записи имени переменной дважды.
Петр Доброгост

130

Как уже было сказано, это не то, что вы делаете в Python - переменные на самом деле являются отображениями имен для объектов.

Однако вот один из способов попробовать это сделать:

 >>> a = 1
 >>> for k, v in list(locals().iteritems()):
         if v is a:
             a_as_str = k
 >>> a_as_str
 a
 >>> type(a_as_str)
 'str'

14
Эта идея имеет свои достоинства, но обратите внимание, что если два имени переменной ссылаются на одно и то же значение (например True), то может быть возвращено непреднамеренное имя переменной.
unutbu

14
Почему id(v) == id(a)вместо v is a? Это не удастся для объектов, связанных с несколькими переменными, такими как целые, строки и любые аналогично реализованные пользовательские типы.

Да, v is aбудет лучшим выбором. И да, безусловно, опасно, учитывая все возможные подводные камни, которые могут возникнуть! ;-)
rlotun

16
@ e-удовлетворительно. Я удивлен, что вы не пометили этот ответ как ответ, поскольку я согласен с вашим комментарием о том, что rlotun ближе к его первоначальному «духу», поскольку он позволяет обнаружить имя . Кроме того, ответ С.Лотта совсем не дает ответа на ваш вопрос ...
Петр Доброгост

2
"перебор и опасность" ... а использование eval не так ли?
ошибка

63

Я хотел сделать это довольно много. Этот хак очень похож на предложение rlotun, но это однострочник, что важно для меня:

blah = 1
blah_name = [ k for k,v in locals().iteritems() if v is blah][0]

Python 3+

blah = 1
blah_name = [ k for k,v in locals().items() if v is blah][0]

3
@keflavich Мне очень понравился этот подход, и я использовал его время от времени. Однако я не могу заставить его работать внутри функций. Я полагаю, что есть «лучшие» способы сделать это, но ни один из них не так хорош, как nbubis. Вы были в состоянии использовать это в функциях keflavich? Здесь я задаю вопрос по этому поводу.
Лев

10
Обратите внимание, что в Python 3 iteritems()заменяется наitems()
Джонатан Уилер

Это ненадежно: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)выходыspam
andreasdr

1
@andreasdr это потому что spam = 1, blah = 1; assert spam is blah. Решение ломается при сравнении примитивных типов данных.
июня 18

17

Это взломать Он не будет работать на всех дистрибутивах реализации Python (в частности, на тех, которые не имеют traceback.extract_stack.)

import traceback

def make_dict(*expr):
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    begin=text.find('make_dict(')+len('make_dict(')
    end=text.find(')',begin)
    text=[name.strip() for name in text[begin:end].split(',')]
    return dict(zip(text,expr))

bar=True
foo=False
print(make_dict(bar,foo))
# {'foo': False, 'bar': True}

Обратите внимание, что этот хак хрупок:

make_dict(bar,
          foo)

(вызов make_dict в 2 строки) не будет работать.

Вместо того , чтобы пытаться генерировать Dict из значений foo и bar, было бы гораздо более Pythonic для создания Dict из строки имен переменных 'foo' и 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])

1
+1 за умный взлом. Конечно, трассировка очень медленная, поэтому использовать ее может быть вялым.
E-удовлетворительно

1
+1111111 !!!! Да, это медленно, но при использовании, чтобы заменить, print("a_very_long_name: {}'.format(a_very_long_name))кто заботится!
14:46

14

Это невозможно в Python, который действительно не имеет «переменных». У Python есть имена, и для одного и того же объекта может быть несколько имен.


да, я знаю, я сделал вопрос простым, но я ожидал большего, например, "get_var_tags (var) [0]".
e-удовлетворительно

10

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

def details(val):
  vn = val.__name__                 #  If such a thing existed
  vs = str(val)
  print("The Value of "+ str(vn) + " is " + vs)
  print("The data type of " + vn + " is " + str(type(val)))

Поэтому, если у вас сложная ситуация со словарем / списком / кортежем, было бы весьма полезно, чтобы интерпретатор возвратил имя переменной, которую вы назначили. Например, вот странный словарь:

m = 'abracadabra'
mm=[]    
for n in m:
  mm.append(n)
mydic = {'first':(0,1,2,3,4,5,6),'second':mm,'third':np.arange(0.,10)}



details(mydic)

The Value of mydic is {'second': ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'], 'third': array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.]), 'first': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
The data type of mydic is <type 'dict'>

details(mydic['first'])
The Value of mydic['first'] is (0, 1, 2, 3, 4, 5, 6)]
The data type of mydic['first'] is <type 'list'>

details(mydic.keys())
The Value of mydic.keys() is ['second', 'third', 'first']
The data type of mydic.keys() is <type 'tuple'>

details(mydic['second'][0])
The Value of mydic['second'][0] is a
The data type of mydic['second'][0] is <type 'str'>

Я не уверен, что поставлю это в нужное место, но подумал, что это может помочь. Я надеюсь, что это так.


Итак, проверяя вашу голову, учитывает ли это тот факт, что переменные / имена могут указывать на разные вещи в разное время в коде? Например, myconnectionможет ли указывать на логическое значение в одной точке, целое число в другое время и соединение с сокетом в другой точке выполнения кода?

9

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

def what(obj, callingLocals=locals()):
    """
    quick function to print name of input and value. 
    If not for the default-Valued callingLocals, the function would always
    get the name as "obj", which is not what I want.    
    """
    for k, v in list(callingLocals.items()):
         if v is obj:
            name = k
    print(name, "=", obj)

использование:

>> a = 4
>> what(a)
a = 4
>>|

6

Я считаю, что если у вас уже есть конкретный список значений, это способ, описанный @S. Лоттс лучший; однако способ, описанный ниже, хорошо работает для добавления всех переменных и классов, добавленных в код, БЕЗ необходимости указывать имя переменной, хотя вы можете указать их, если хотите. Код можно расширить, чтобы исключить классы.

import types
import math  # mainly showing that you could import what you will before d

# Everything after this counts
d = dict(globals())

def kv_test(k,v):
    return (k not in d and 
            k not in ['d','args'] and
            type(v) is not types.FunctionType)

def magic_print(*args):
    if len(args) == 0: 
        return {k:v for k,v in globals().iteritems() if kv_test(k,v)}
    else:
        return {k:v for k,v in magic_print().iteritems() if k in args}

if __name__ == '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

Вывод:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}

6

В питоне 3 это легко

myVariable = 5
for v in locals():
  if id(v) == id("myVariable"):
    print(v, locals()[v])

это напечатает:

myVariable 5


Это похоже на подход Рлотуна, но немного проще
официальные

10
-1. Откройте новое окно интерпретатора и попробуйте for v in locals().
эфир

Я не совсем уверен, что вы имеете в виду?
Официальные

4
Это приведет к ошибке: RuntimeError: словарь изменил размер во время итерации ...
Низар Б.

2
однако вы можете сделатьfor v in list(locals()):
Phylliida

5

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

def varname(var):
  import inspect
  frame = inspect.currentframe()
  var_id = id(var)
  for name in frame.f_back.f_locals.keys():
    try:
      if id(eval(name)) == var_id:
        return(name)
    except:
      pass

Хороший ответ, но для меня это лучше с: ... id (eval (name, None, frame.f_back.f_locals)) == ...
Эммануэль ДУМАС

5

Вот функция, которую я создал для чтения имен переменных. Он более общий и может использоваться в разных приложениях:

def get_variable_name(*variable):
    '''gets string of variable name
    inputs
        variable (str)
    returns
        string
    '''
    if len(variable) != 1:
        raise Exception('len of variables inputed must be 1')
    try:
        return [k for k, v in locals().items() if v is variable[0]][0]
    except:
        return [k for k, v in globals().items() if v is variable[0]][0]

Чтобы использовать его в указанном вопросе:

>>> foo = False
>>> bar = True
>>> my_dict = {get_variable_name(foo):foo, 
               get_variable_name(bar):bar}
>>> my_dict
{'bar': True, 'foo': False}

4

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

От: [effbot.org] ( http://effbot.org/zone/python-objects.htm#names )

Имена немного отличаются - они на самом деле не являются свойствами объекта, а сам объект не знает, как он называется.

Объект может иметь любое количество имен или вообще не иметь имени.

Имена живут в пространствах имен (таких как пространство имен модуля, пространство имен экземпляра, локальное пространство имен функции).

Обратите внимание: он говорит, что сам объект не знает, как он называется , так что это была подсказка. Объекты Python не являются самоссылочными. Тогда это говорит, Имена живут в пространствах имен . У нас это есть в TCL / TK. Так что, возможно, мой ответ поможет (но это помогло мне)

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    печать dir ()

166707048
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']

Таким образом, в конце списка стоит «jj».

Перепишите код как:

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    для х в директории ():
        распечатать идентификатор (eval (x))

161922920
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']
3077447796
136515736
3077408320
3077656800
136515736
161922920

Этот неприятный фрагмент кода - это имя переменной / объекта / что угодно, что вы называете педантикой.

Итак, вот оно. Адрес памяти 'jj' тот же, когда мы ищем его напрямую, как и когда мы ищем словарь в глобальном пространстве имен. Я уверен, что вы можете сделать функцию для этого. Просто запомните, в каком пространстве имен находится ваша переменная / объект / wypci.

QED.


6
У вас есть два сумасшедших использования eval здесь. Первый точно такой же , как: print id(jj). Второй просто ищет имя, и его можно сделать проще vars().
Нед Бэтчелдер

2

Может быть, я думаю об этом, но ..

str_l = next((k for k,v in locals().items() if id(l) == id(v)))


>>> bar = True
>>> foo = False
>>> my_dict=dict(bar=bar, foo=foo)
>>> next((k for k,v in locals().items() if id(bar) == id(v)))
'bar'
>>> next((k for k,v in locals().items() if id(foo) == id(v)))
'foo'
>>> next((k for k,v in locals().items() if id(my_dict) == id(v)))
'my_dict'

Большой! Это то, что я искал. Спасибо @ rh0dium ... \ nvariable = 1 \n [k for k,v in locals().items() if id(variable) == id(v)] \n Out[14]: ['variable']
Маджди

2
import re
import traceback

pattren = re.compile(r'[\W+\w+]*get_variable_name\((\w+)\)')
def get_variable_name(x):
    return pattren.match( traceback.extract_stack(limit=2)[0][3]) .group(1)

a = 1
b = a
c = b
print get_variable_name(a)
print get_variable_name(b)
print get_variable_name(c)

2

Я загрузил решение для Pypi . Это модуль, определяющий эквивалент функции C # nameof.

Он перебирает инструкции байт-кода для вызываемого кадра, получая имена переменных / атрибутов, передаваемых ему. Имена находятся в .argreprв LOADинструкции следующего имени функции.



1

Большинство объектов не имеют атрибута __name__ . (Классы, функции и модули делают; есть ли еще встроенные типы, которые есть?)

Что еще вы ожидаете, print(my_var.__name__)кроме print("my_var")? Вы можете просто использовать строку напрямую?

Вы могли бы «нарезать» диктовку:

def dict_slice(D, keys, default=None):
  return dict((k, D.get(k, default)) for k in keys)

print dict_slice(locals(), ["foo", "bar"])
# or use set literal syntax if you have a recent enough version:
print dict_slice(locals(), {"foo", "bar"})

В качестве альтернативы:

throw = object()  # sentinel
def dict_slice(D, keys, default=throw):
  def get(k):
    v = D.get(k, throw)
    if v is not throw:
      return v
    if default is throw:
      raise KeyError(k)
    return default
  return dict((k, get(k)) for k in keys)

2
+1 но я знаю, что этого имени не существует, почему все воспринимают это «что-то вроде» буквально? Ваше решение не решает проблему, так как я не хочу кодировать имя, в противном случае я бы сделал точное решение, которое я уже дал в вопросе.
e-удовлетворительно

3
@ e-satin: Если простое использование всего в localals () решит вашу проблему, я понятия не имею, о чем вы спрашиваете. Я предполагаю, что вы в порядке с вызовом some_func(var), поэтому я попытался указать, что это не очень далеко some_func("var"), с dictslice, позволяющим вам получить отображение имя-значение для нескольких переменных одновременно.

1

Ну, я столкнулся с той же самой потребностью несколько дней назад и должен был получить имя переменной, которая указывала бы на объект сам .

И почему это было так необходимо?

Короче говоря, я строил плагин для Maya . Основной плагин был построен с использованием C ++, но графический интерфейс рисуется через Python (так как он не интенсивно использует процессор). Поскольку я пока не знаю, как returnумножить значения из плагина, кроме значения по умолчанию MStatus, поэтому для обновления словаря в Python мне пришлось передать имя переменной, указывая на объект, реализующий графический интерфейс, и который содержит сам словарь, подключаемый модуль, а затем использовать MGlobal::executePythonCommand()для обновления словаря из глобальной области видимости Maya .

Чтобы сделать то, что я сделал, было что-то вроде:

import time

class foo(bar):

    def __init__(self):
        super(foo, self).__init__()
        self.time = time.time() #almost guaranteed to be unique on a single computer

    def name(self):
        g = globals()
        for x in g:
            if isinstance(g[x], type(self)):
                if g[x].time == self.time:
                    return x
                    #or you could:
                    #return filter(None,[x if g[x].time == self.time else None for x in g if isinstance(g[x], type(self))])
                    #and return all keys pointing to object itself

Я знаю, что это не идеальное решение, поскольку во globalsмногих ключах можно указывать на один и тот же объект, например:

a = foo()
b = a
b.name()
>>>b
or
>>>a

и что этот подход не является потокобезопасным. Поправь меня, если я ошибаюсь.

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

Я попробовал это на int(примитивный целочисленный класс), но проблема в том, что эти примитивные классы не обойдутся (пожалуйста, исправьте используемую техническую терминологию, если она ошибочна). Вы могли бы повторно реализовать, intа затем сделать, int = fooно a = 3никогда не будет объектом, fooно примитива. Чтобы преодолеть это, вы должны a = foo(3)приступить a.name()к работе.


1

В Python 2.7 и новее есть также словарное понимание, которое делает его немного короче. Если возможно, я бы использовал getattr вместо eval (eval is evil), как в верхнем ответе. Самость может быть любым объектом, контекст которого вы видите. Это может быть объект или locals = localals () и т. Д.

{name: getattr(self, name) for name in ['some', 'vars', 'here]}

1

Я работал над похожей проблемой. @ S.Lott сказал: «Если у вас есть список переменных, какой смысл« открывать »их имена?» И мой ответ - просто посмотреть, можно ли это сделать, и если по какой-то причине вы хотите отсортировать переменные по типу в списках. Так или иначе, в моем исследовании я натолкнулся на эту тему, и мое решение немного расширено и основано на решении @rlotun. @Unutbu сказал: «Эта идея имеет свои достоинства, но учтите, что если два имени переменной ссылаются на одно и то же значение (например, True), то может быть возвращено непреднамеренное имя переменной». В этом упражнении , что было правдой , так я имел дело с ним, используя список понимание подобного этому для каждой возможности: isClass = [i for i in isClass if i != 'item']. Без этого «элемент» будет отображаться в каждом списке.

__metaclass__ = type

from types import *

class Class_1: pass
class Class_2: pass
list_1 = [1, 2, 3]
list_2 = ['dog', 'cat', 'bird']
tuple_1 = ('one', 'two', 'three')
tuple_2 = (1000, 2000, 3000)
dict_1 = {'one': 1, 'two': 2, 'three': 3}
dict_2 = {'dog': 'collie', 'cat': 'calico', 'bird': 'robin'}
x = 23
y = 29
pie = 3.14159
eee = 2.71828
house = 'single story'
cabin = 'cozy'

isClass = []; isList = []; isTuple = []; isDict = []; isInt = []; isFloat = []; isString = []; other = []

mixedDataTypes = [Class_1, list_1, tuple_1, dict_1, x, pie, house, Class_2, list_2, tuple_2, dict_2, y, eee, cabin]

print '\nMIXED_DATA_TYPES total count:', len(mixedDataTypes)

for item in mixedDataTypes:
    try:
        # if isinstance(item, ClassType): # use this for old class types (before 3.0)
        if isinstance(item, type):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isClass.append(mapping_as_str)
            isClass = [i for i in isClass if i != 'item']

        elif isinstance(item, ListType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isList.append(mapping_as_str)
            isList = [i for i in isList if i != 'item']

        elif isinstance(item, TupleType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isTuple.append(mapping_as_str)
            isTuple = [i for i in isTuple if i != 'item']

        elif isinstance(item, DictType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isDict.append(mapping_as_str)
            isDict = [i for i in isDict if i != 'item']

        elif isinstance(item, IntType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isInt.append(mapping_as_str)
            isInt = [i for i in isInt if i != 'item']

        elif isinstance(item, FloatType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isFloat.append(mapping_as_str)
            isFloat = [i for i in isFloat if i != 'item']

        elif isinstance(item, StringType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isString.append(mapping_as_str)
            isString = [i for i in isString if i != 'item']

        else:
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    other.append(mapping_as_str)
            other = [i for i in other if i != 'item']

    except (TypeError, AttributeError), e:
        print e

print '\n isClass:', len(isClass), isClass
print '  isList:', len(isList), isList
print ' isTuple:', len(isTuple), isTuple
print '  isDict:', len(isDict), isDict
print '   isInt:', len(isInt), isInt
print ' isFloat:', len(isFloat), isFloat
print 'isString:', len(isString), isString
print '   other:', len(other), other

# my output and the output I wanted
'''
MIXED_DATA_TYPES total count: 14

 isClass: 2 ['Class_1', 'Class_2']
  isList: 2 ['list_1', 'list_2']
 isTuple: 2 ['tuple_1', 'tuple_2']
  isDict: 2 ['dict_1', 'dict_2']
   isInt: 2 ['x', 'y']
 isFloat: 2 ['pie', 'eee']
isString: 2 ['house', 'cabin']
   other: 0 []
'''

Проблема, которую я хотел бы принять, заключается в том, что имена не являются свойствами объектов. Один объект может иметь несколько имен или вообще не иметь имени. Например, если вы добавили pi = pieсвой код, вы получите дополнительную запись в своем isFloatсписке. Если вы добавили tuple_1[0]в свой mixedDataTypesсписок, имя для него не будет найдено, несмотря на то, что «один» присутствует в вашем коде дважды (хотя благодаря интернированию строк они оба будут ссылками на один и тот же объект).
Blckknght

1
@Blckknght --- Я согласен. Это просто еще один способ сделать что-то, чего на самом деле не должно было быть. Я не говорил, что это дает уникальные результаты или что это безошибочно. При этом я обнаружил, что использование piи в eкачестве переменных вызывает нежелательный вывод, и это потому, что оба являются частью mathбиблиотеки. Для меня это было просто упражнение, чтобы увидеть, можно ли это сделать, хотя конечный результат не идеален. В моем изучении этого языка чтение книг только заходит так далеко. По моему мнению, если вы действительно хотите выучить язык, вам нужно сыграть «что если» и посмотреть, что вы придумали.
Майкл Шварц

1

вы можете использовать easydict

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1
>>> d = edict(foo=3)
>>> d.foo
3

другой пример:

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]

1

На python3 эта функция получит самое внешнее имя в стеке:

import inspect


def retrieve_name(var):
        """
        Gets the name of var. Does it from the out most frame inner-wards.
        :param var: variable to get name from.
        :return: string
        """
        for fi in reversed(inspect.stack()):
            names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
            if len(names) > 0:
                return names[0]

Это полезно в любом месте кода. Обходит перевернутый стек в поисках первого совпадения.


0

Хотя это, вероятно, ужасная идея, она совпадает с ответом rlotun, но чаще будет возвращать правильный результат.

import inspect
def getVarName(getvar):
  frame = inspect.currentframe()
  callerLocals = frame.f_back.f_locals
  for k, v in list(callerLocals.items()):
    if v is getvar():
      callerLocals.pop(k)
      try:
        getvar()
        callerLocals[k] = v
      except NameError:
        callerLocals[k] = v
        del frame
        return k
  del frame

Вы называете это так:

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"

0

должен получить список, а затем вернуть

def get_var_name(**kwargs):
    """get variable name
        get_var_name(var = var)
    Returns:
        [str] -- var name
    """
    return list(kwargs.keys())[0]

0

Он не будет возвращать имя переменной, но вы можете легко создать словарь из глобальной переменной.

class CustomDict(dict):
    def __add__(self, other):
        return CustomDict({**self, **other})

class GlobalBase(type):
    def __getattr__(cls, key):
        return CustomDict({key: globals()[key]})

    def __getitem__(cls, keys):
        return CustomDict({key: globals()[key] for key in keys})

class G(metaclass=GlobalBase):
    pass

x, y, z = 0, 1, 2

print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}

0

С python-varnameвами легко можно сделать это:

pip install python-varname

from varname import Wrapper

foo = Wrapper(True)
bar = Wrapper(False)

your_dict = {val.name: val.value for val in (foo, bar)}

print(your_dict)

# {'foo': True, 'bar': False}

Отказ от ответственности: я являюсь автором этой библиотеки python-varname.


-1
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

таким образом получить varname для возможно 'a' или 'b'.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.