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'

Python 3.6の新しい f-string機能を使用して、 locals()は不要になりました:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> f'{zip: >5} {name.upper()}'
'  123 FOO'

他のヒント

元のリスト [foo、bar、baz] には変数 names は含まれず、同じ values を参照する要素のみが含まれますリストした変数としてem>。これは、同じ値を参照する2つの異なる変数名を持つことができるためです。

したがって、リスト自体には、オブジェクトを参照する他の名前に関する情報は含まれません。配列の最初の要素の名前は 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の癖です。

リストまたはジェネレーター内包表記を使用して、辞書の直接インスタンス化に使用されるキー、値タプルのリストを作成できます。最適な方法は次のとおりです。

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

さらに、たとえば、変数がローカルシンボルテーブルに存在することがわかっている場合は、ローカルから直接変数を調べることにより、危険な評価から自分を救うことができます。

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

最終更新後、以下の答えが本当にあなたの望むものだと思います。制御する文字列の文字列展開にこれを使用している場合は、locals()を文字列展開に直接渡すだけで、目的の値が選択されます

ただし、これらの文字列が外部ソース(翻訳ファイルなど)からのものである可能性がある場合は、locals()をフィルタリングすることをお勧めします

効率的ではありませんが、 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)

必要に応じて。

scroll top