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


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.