2

これは、ここで提供されるソリューションに関連する質問です。ソリューションとして次のコードが含まれます。

from collections import MutableMapping

def set_value(d, keys, newkey, newvalue, default_factory=dict):
    """
    Equivalent to `reduce(dict.get, keys, d)[newkey] = newvalue`
    if all `keys` exists and corresponding values are of correct type
    """
    for key in keys:
        try:
            val = d[key]
        except KeyError:
            val = d[key] = default_factory()
        else:
            if not isinstance(val, MutableMapping):
                val = d[key] = default_factory()
        d = val
    d[newkey] = newvalue

このコードが機能する理由を誰かが説明してくれることを願っています。渡された dict 'd' が d = val の場所で常に上書きされないことに混乱しています。dict 'd' は、次のノードにインデックスを付けずに、さらにネストされた辞書を取得し続けるにはどうすればよいですか? 意味が分からない場合は申し訳ありませんが、これがどのように機能するかわかりません。

ご協力いただきありがとうございます!

4

2 に答える 2

2

dリバウンドです。val変数は、各ループで指すように更新されます。

のそれぞれについてkeykeysキーが見つかる (val = d[key]成功する) か、default_factory()を使用してそのキーの新しい値を作成します。

キーが見つかったが、値が型ではなかった場合、見つかった値は新しい結果MutableMappingに置き換えられます。default_factory()

このレベルの新しい値が決定されると、dは古いディクショナリを忘れて、代わりに新しいディクショナリを指すように指示されます。

再バインドしても古い値は変更されません。その古い値の参照を停止するだけです。

簡単な例を使ってみましょう:

>>> d = {'foo': {}}
>>> keys = ['foo']
>>> newkey = 'bar'
>>> newval = 'eggs'
>>> original = d

最初は、originaldは同じオブジェクトです。ここでの名前は紙のラベル、値はバルーンと考えてください。ラベルは風船に紐で結ばれています。上記の例では、dとのoriginalラベルが両方とも同じ辞書バルーンに結び付けられています。

for key in keysループに入ると、d[key]ルックアップが成功し、空の辞書であるvalの結果に関連付けられます。d['foo']

>>> key = keys[0]
>>> key
'foo'
>>> val = d[key]
>>> val
{}

これは通常の Python 辞書でありisinstance(val, MutableMapping)True. 次の行は、ラベルをそのディクショナリに再バインドします。文字列は元の辞書からd単純に結び付けられておらvalず、結び付けられている同じバルーンに関連付けられています。

>>> d = val
>>> d
{}
>>> original
{'foo': {}}
>>> d is val
True
>>> d is original
False

元の辞書は再バインドによって変更されませんでした!

キーが不足すると ( には 1 つしかありませんでしたkeys)、次の部分で次のように割り当てnewvalられd[newkey]ます。

>>> d[newkey] = newval
>>> d
{'bar': 'eggs'}

しかし、dこの辞書吹き出しに付いているラベルはそれだけではありません。辞書自体にはキーと値が含まれており、どちらもバルーンに結び付けられたラベルです! originalラベルはまだ外側のディクショナリ バルーンに関連付けられており、ネストされたディクショナリに関連付けられたキーfooに関連付けられた値があり、変更したのはこのネストされたディクショナリです。

>>> original
{'foo': {'bar': 'eggs'}}

アルゴリズムは、文字列を介して新しい辞書へのラベルをたどっただけです。

より複雑なキーの組み合わせを使用するということは、より多くの文字列がたどられることを意味し、おそらく追加の辞書が結び付けられるために汲み上げられます.

于 2013-09-08T23:24:14.800 に答える
1

あなたの質問は次のように要約されると思います:

オブジェクトに対して何もしないのに、オブジェクトd[newkey] = newvalueを変更するのはなぜですか?d = var

Python では、関数内の変更可能なオブジェクトを変更できますが、外部の名前が参照するオブジェクトを変更することはできません。

于 2013-09-09T00:07:58.577 に答える