2017-07-26 9 views
0

これはPython 3.5環境です。コードは自明ですが、ここでは両方の関数が動作することを期待していますが、正しいものは1つだけです。dictsが期待どおりに動作しないpython 3.5

TLDR: out = {**out, **answer}を割り当てると、outは右キーを含む変数になりますが、次の2ステップでは失われます。 c = {**c,**a}を割り当てるとテスト機能で完全に機能し、新しいキーは失われません。

誰かが私が間違っていることを説明できますか?関数であるので

out = {**out, **answer} # out is now a different object 

:私は違いはそれはあなたが関数に渡す辞書から取り外された後、第二の機能では、あなたがout変数を再割り当てすることをだと思う

def flatify_works(d, out, fhook=None): 
    for k, v in d.items(): 
     if not isinstance(v, dict) and not isinstance(v, list): 
      out[k] = v 
     elif isinstance(v, dict): 
      flatify_works(v, out, fhook) 
     elif isinstance(v, list): 
      if fhook is None: 
       raise AssertionError("an array with more than 1 elment found.") 
      answer = fhook(k, v) 
      for k, v in answer.items(): 
       out[k] = v 


def flatify_doesnt_work(d, out, fhook=None): 
    for k, v in d.items(): 
     if not isinstance(v, dict) and not isinstance(v, list): 
      out[k] = v 
     elif isinstance(v, dict): 
      flatify_doesnt_work(v, out, fhook) 
     elif isinstance(v, list): 
      if fhook is None: 
       raise AssertionError("an array with more than 1 elment found.") 
      answer = fhook(k, v) 
      out = {**out, **answer} # put a breakpoint here, and go 2 steps further 


def hook(k, v): 
    l = [d["c"] for d in v] 
    return {"c": sum(l), "d": "blabla"} 


def test_merge_dicts(): 
    a = {"a": 1, "b": 2} 
    c = {"c": 3} 
    c = {**c, **a} # merging works perfectly here 
    print(c) 
    assert "a" in c and "b" in c and "c" in c # ok 


def test_nested_works(): 
    out = {} 
    flatify_works({"a": 1, "b": [{"c": 0.6, "d": 4}, {"c": 0.4, "d": 4}]}, out, hook) 
    print("working exemple: {}".format(str(out))) 


def test_nested_doesnt_work(): 
    out = {} 
    flatify_doesnt_work({"a": 1, "b": [{"c": 0.6, "d": 4}, {"c": 0.4, "d": 4}]}, out, hook) 
    print("not working exemple: {}".format(str(out))) 


def main(): 
    test_merge_dicts() # ok 
    test_nested_works() # ok 
    test_nested_doesnt_work() # why out = {**out, **answer} is not working as expected? 


if __name__ == '__main__': 
    main() 
+0

は、多くのコードが実際にこの問題を実証するために必要なことですか? –

+0

私は知っていません、それは十分ではない以上に良いですか? – dgan

+3

これを最小限に抑えることができます。あなたの質問のタイトルに基づいて、私はあなたの例が2つの辞書、その正確な論理を担当するコード、それがどのように壊れているかを示す出力、そしてどのように見えるべきかを期待します。 – idjaw

答えて

2

再帰的な変更は、元のdictには影響しません。最初の関数で

、しかし、あなただけの予想通り、場所でdictのを修正した項目の割り当てを、実行します。

out[k] = v 
+0

同じネームの2つの異なるオブジェクトを同じスコープで作成することはできないと思いましたか? – dgan

+0

@DenisGantsev名前は、任意の時点で1つのオブジェクトを参照します。代入文は、名前が別のオブジェクトにバインドされているときです。 –

+0

ハム、これは感覚を作る! – dgan

関連する問題