Учитывая список имен переменных в 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)
в зависимости от того, что вы хотите.