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

StackOverflow https://stackoverflow.com/questions/230896

  •  04-07-2019
  •  | 
  •  

Вопрос

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

['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'])
Это было полезно?

Решение

Забудьте о фильтрации 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'

Другие советы

Ваш оригинальный список [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)

Необходимость импортировать __main __ , когда ваш код находится в неназванном главном модуле, - это особенность Python.

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top