Учитывая список имен переменных в Python, как мне создать словарь с именами переменных в виде ключей (к значениям переменных)?

У меня есть список имен переменных, например:

['foo', 'bar', 'baz']

(Первоначально я спросил, как я конвертирую список переменных. См. ниже ответ Грега Хьюглилла.)

Как мне преобразовать это в словарь, где ключи являются именами переменных (как строки), а значениями являются значения переменных?

{'foo': foo, 'bar': bar, 'baz': baz}

Теперь, когда я повторно задаю вопрос, я придумал:

d = {}
for name in list_of_variable_names:
    d[name] = eval(name)

Можно ли улучшить это?

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

Я часто обнаруживаю, что я использую оператор% для строк со словарем имен и значений для интерполяции. Часто имена в строке - это просто имена локальных переменных. Итак (с ответом ниже) я могу сделать что-то вроде этого:

message = '''Name: %(name)s
ZIP: %(zip)s

Dear %(name)s,
...''' % dict((x, locals()[x]) for x in ['name', 'zip'])

Ответы

Ответ 1

Заблокировать фильтрацию locals()! Словарь, который вы передаете строке форматирования, может содержать неиспользуемые ключи:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> locals()
{'name': 'foo', 'zip': 123, ... 'unused': 'whoops!', ...}
>>> '%(name)s %(zip)i' % locals()
'foo 123'

Ответ 2

В исходном списке [foo, bar, baz] нет имен переменных, он содержит только элементы, которые относятся к тем же значениям, что и перечисленные вами переменные. Это связано с тем, что вы можете иметь два разных имени переменной, которые ссылаются на одно и то же значение.

Таким образом, список сам по себе не содержит информации о том, что другие имена относятся к объектам. Первый элемент в вашем массиве имеет имя foo, но также имеет имя a[0] (предполагая, что ваш массив называется a). После выполнения следующего кода quux также ссылается на тот же объект:

quux = a[0]

Обновление: вы правы, что можете использовать eval() для этого, но его использование обычно не рекомендуется. Python предоставляет специальный член с именем __dict__, который содержит таблицу символов для текущего модуля. Таким образом, вы можете:

import __main__
d = dict((x, __main__.__dict__[x]) for x in list_of_variable_names)

Наличие import __main__, когда ваш код находится в неназванном главном модуле, является причудой Python.

Ответ 3

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

dict((name, eval(name)) for name in list_of_variable_names)

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

dict((name, locals()[name]) for name in list_of_variable_names)

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

Если, однако, эти строки могут когда-либо возникать из внешнего источника (например, файлов перевода), чем хорошая идея фильтровать locals()

Ответ 4

Неэффективно, но без вызова eval:

dict((k,v) for (k,v) in globals().iteritems() if k in list_of_variable_names)

или

dict((k,v) for (k,v) in vars().iteritems() if k in list_of_variable_names)

в зависимости от того, что вы хотите.