50

私はPythonを勉強しており、現在辞書を使ってさらに学習しています。

私は考えていた;

次のような辞書があり、d = {'key_1': 'value_a', 'key_2': 'value_b'}この辞書を変数に分割/分割したい場合、各変数は辞書のキーであり、各変数の値は辞書のそのキーの値です。

これを達成するための最良のPythonicの方法は何でしょうか?

d = {'key_1': 'value_a', 'key_2': 'value_b'}
#perform the command and get
key_1 = 'value_a'
key_2 = 'value_b'

私は試しました:key_1, key_2 = dしかし、うまくいきませんでした。

基本的に、2行のコードを1行に減らすより良い方法があるかどうかを調べるために、専門家の知恵を求めています。

注: これは動的変数の作成ではありません。

4

10 に答える 10

28

問題は、辞書が順序付けされていないため、単純なアンパックを使用できないことですd.values()。もちろん、最初に dict をキーで並べ替えてから、値をアンパックすることもできます。

# Note: in python 3, items() functions as iteritems() did
#       in older versions of Python; use it instead
ds = sorted(d.iteritems())
name0, name1, name2..., namen = [v[1] for v in ds]

少なくともオブジェクト内で、次のようなこともできます。

for k, v in dict.iteritems():
    setattr(self, k, v)

さらに、上記のコメントで述べたように、アンパックされた辞書を変数として必要とするすべてのロジックを関数に取得できる場合は、次のようにすることができます。

def func(**kwargs):
    # Do stuff with labeled args

func(**d)
于 2012-06-22T13:11:00.693 に答える
23

これまでに言及されていない解決策は、

dictget = lambda d, *k: [d[i] for i in k]

そしてそれを使用します:

key_1, key_2 = dictget(d, 'key_1', 'key_2')

その利点は、取得する変数が多くても非常に読みやすいことです。

ただし、さらに読みやすいのは、次のような「実際の」関数です。

def dictget(d, *k):
    """Get the values corresponding to the given keys in the provided dict."""
    return [d[i] for i in k]
    # or maybe
    return (d[i] for i in k) # if we suppose that we have bigger sets of result
    # or, equivalent to this
    for i in k:
        yield d[i]

これは、docstring によるコメントもサポートしており、推奨されます。

于 2012-06-22T13:51:37.923 に答える
5
var1, var2 = (lambda key1, key2: (key1, key2))(**d)

コードを読んでいる人に頭痛の種を与えたい場合は、無名関数を使用してこのような値をアンパックできます。

于 2013-08-27T12:53:17.333 に答える
4

勇気があれば、これを行うことができます:

for k, v in d.items():
    locals()[k] = v

しかし、勇敢であるだけでは十分ではないかもしれません - 無謀である必要があるかもしれません。

@ecatmur のような無謀なヒーローになりたい場合は、次のようにします。

locals().update(d)

しかし、OPが質問を更新してコメントに答えたので、これは彼が本当にやりたいことではないようです。記録のために: 変数を動的に作成するのには十分な理由があります - ここにいる誰もがそれがpythonicではないことに同意しているとしても. 多くのインタプリタ スタイルの問題は、スコープを動的に変更することできちんと解決できます。制御された方法でこれを行うだけです。そして...ええと、これを本番サイトに展開しないでください;)

于 2012-06-22T13:15:47.297 に答える
2

私はこれがあなたの問題を解決するはずだと思います

d = {'key_1': 'value_a', 'key_2': 'value_b'}
for k,v in d.items():
    exec '%s=%s'%(k,v)
于 2012-06-22T17:38:06.447 に答える
2

私は実際に、__init__オブジェクト構築時にメソッドのすべての引数を self 名前空間にプルするユースケースを持っています:

vars(self).update(somedict)

vars関数は、渡されたオブジェクトに関連付けられた「名前空間」の辞書を取得します。ただし、CPython 実装の詳細により、これは関数内のローカルでは機能しません。したがって、すべてのインタープリターで機能するわけではありません。

グローバル名前空間の場合は に置き換えますがvars(self)globals()これは実際にはロジックに問題があることを示しています。前述のように、ローカル変数の場合、これはとにかく機能しません ( NameErrordict に値を割り当てたとしても機能します)。

于 2012-06-22T13:15:00.937 に答える
0

変数名のソースを見つけるのが非常に難しくなるため、変数を動的に宣言することはお勧めしません。そうは言っても、Pythonでソリューションの動的変数名をハックすることは可能ですが、お勧めしません。おそらく、普通の古い辞書を使用する方がよいでしょう。

于 2012-06-22T13:14:30.667 に答える