Более простой способ создать словарь отдельных переменных? - PullRequest
217 голосов
/ 31 марта 2010

Я хотел бы иметь возможность получить имя переменной в виде строки, но я не знаю, обладает ли 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(), так что я думаю, что есть способ.

Ответы [ 25 ]

130 голосов
/ 31 марта 2010

Как уже говорилось, это не то, что вы делаете в 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'
62 голосов
/ 26 июня 2011

Я очень хотел это сделать. Этот хак очень похож на предложение 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]
48 голосов
/ 31 марта 2010

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

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}
17 голосов
/ 31 марта 2010

Это хак. Он не будет работать во всех дистрибутивах реализации 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 строки) не будет работать.

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

dict([(name,locals()[name]) for name in ('foo','bar')])
14 голосов
/ 31 марта 2010

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

10 голосов
/ 04 июня 2013

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

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'>

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

8 голосов
/ 22 мая 2017

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

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 голосов
/ 07 ноября 2013

Я считаю, что если у вас уже есть конкретный список значений, этот способ описывается @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 голосов
/ 05 марта 2014

В Python 3 это просто

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

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

myVariable 5

5 голосов
/ 05 декабря 2016

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

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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...