Учитывая список имен переменных в Python, как создать словарь с именами переменных в качестве ключей (для значений переменных)? - PullRequest
14 голосов
/ 23 октября 2008

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

['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'])

Ответы [ 4 ]

16 голосов
/ 24 октября 2008

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

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

С новой функцией f-string в Python 3.6 использование locals() больше не требуется:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> f'{zip: >5} {name.upper()}'
'  123 FOO'
4 голосов
/ 23 октября 2008

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

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

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

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

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

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

4 голосов
/ 23 октября 2008

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

Таким образом, сам по себе список не содержит информации о том, какие другие имена относятся к объектам. Первый элемент в вашем массиве имеет имя 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.

1 голос
/ 23 октября 2008

Не эффективно, но без вызова 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)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...