web-dev-qa-db-ja.com

構造化バインド辞書コンテンツ

辞書を「分解」して、キーの後に値を変数名に関連付けようとしています。何かのようなもの

_params = {'a':1,'b':2}
a,b = params.values()
_

ただし、辞書は順序付けされていないため、params.values()が_(a, b)_の順序で値を返す保証はありません。これを行う良い方法はありますか?

55
hatmatrix

ローカル辞書の使用に関連する問題を恐れており、元の戦略に従うことを好む場合、python 2.7 and 3.1 collections.OrderedDicts の順序付き辞書辞書アイテムを最初に挿入した順序で復元できます

7
joaquin

Jochenの提案よりも少ない繰り返しでこれを行う1つの方法は、ヘルパー関数を使用することです。これにより、変数名を任意の順序でリストし、辞書にあるもののサブセットのみを分解する柔軟性が得られます。

pluck = lambda dict, *args: (dict[arg] for arg in args)

things = {'blah': 'bleh', 'foo': 'bar'}
foo, blah = pluck(things, 'foo', 'blah')

また、joaquinのOrderedDictの代わりに、キーをソートして値を取得することもできます。唯一の問題は、アルファベット順で変数名を指定し、dictのすべてを分解する必要があることです。

sorted_vals = lambda dict: (t[1] for t in sorted(dict.items()))

things = {'foo': 'bar', 'blah': 'bleh'}
blah, foo = sorted_vals(things)
25
ShawnFumo
from operator import itemgetter

params = {'a': 1, 'b': 2}

a, b = itemgetter('a', 'b')(params)

複雑なラムダ関数や辞書を理解する代わりに、組み込みライブラリを使用することもできます。

24
Zachary822

Pythonは、辞書ではなくシーケンスのみを「分解」することができます。したがって、必要なものを書き込むには、必要なエントリを適切なシーケンスにマップする必要があります。私自身、私が見つけることができる最も近い一致は(あまりセクシーではありません)です:

a,b = [d[k] for k in ('a','b')]

これはジェネレーターでも動作します:

a,b = (d[k] for k in ('a','b'))

ここに完全な例があります:

>>> d = dict(a=1,b=2,c=3)
>>> d
{'a': 1, 'c': 3, 'b': 2}
>>> a, b = [d[k] for k in ('a','b')]
>>> a
1
>>> b
2
>>> a, b = (d[k] for k in ('a','b'))
>>> a
1
>>> b
2
14
Sylvain Leroux

たぶん、あなたは本当にこのようなことをしたいですか?

def some_func(a, b):
  print a,b

params = {'a':1,'b':2}

some_func(**params) # equiv to some_func(a=1, b=2)
8
Jochen Ritzel

JSで 破壊的な代入 が機能するのと同じように、これを行う別の方法を次に示します。

params = {'b': 2, 'a': 1}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)

(**を使用して)params辞書をキー値にアンパックすることで( Jochenの答え のように)、ラムダ署名でそれらの値を取得し、キー名に従って割り当てました-そして、これがおまけです-ラムダの署名にnotの辞書もあるので、

params = {'b': 2, 'a': 1, 'c': 3}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)

ラムダが適用された後、残りの変数は次のようになります:{'c':3}

辞書から不要なキーを除外するのに役立ちます。

お役に立てれば。

4
user965011

これを試して

d = {'a':'Apple', 'b':'Banana','c':'Carrot'}
a,b,c = [d[k] for k in ('a', 'b','c')]

結果:

a == 'Apple'
b == 'Banana'
c == 'Carrot'
3
Junaid

まあ、クラスでこれらが必要な場合はいつでもこれを行うことができます:

class AttributeDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttributeDict, self).__init__(*args, **kwargs)
        self.__dict__.update(self)

d = AttributeDict(a=1, b=2)
2
abyx

@ShawnFumoの回答に基づいて私はこれを思いつきました:

def destruct(dict): return (t[1] for t in sorted(dict.items()))

d = {'b': 'Banana', 'c': 'Carrot', 'a': 'Apple' }
a, b, c = destruct(d)

(dict内のアイテムの順序に注意してください)

0
Richard

いいスタイルかどうかわかりませんが

locals().update(params)

トリックを行います。次に、ab、およびparams辞書にあるものはすべて、対応するローカル変数として使用できます。

0
Johannes Charra