1

ここにある再帰辞書のソリューションから、次のPythonレシピを見ました。

class RecursiveDict(dict):
    """Implementation of perl's autovivification feature."""
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value

行についてvalue = self[key] = type(self)():次のコードに比べて長所または短所はありますか?それとも単なる構文ですか?

self[key] = type(self)()
value = self[key]
4

2 に答える 2

4

これは主に構文糖衣ですが、リストするステートメントには当てはまりません。代わりに、それはと同等です

value = type(self)()
self[key] = value

違いを確認するには、Pythonプロンプトで次のように入力します。

>>> class FakeDict(object):
...  def __setitem__(self, k, v):
...   pass
...  def __getitem__(self, k):
...   raise KeyError("boom!")
... 
>>> d = FakeDict()
>>> x = d[1] = 42
>>> d[1] = 42
>>> x = d[1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __getitem__
KeyError: boom!

もちろん、行儀が良けれdictば、これは問題ではありませんが、

self[key] = type(self)()
value = self[key]

2行目で余分なルックアップを実行するdictため、ループ内で省略形を使用するとパフォーマンスが向上する場合があります。

一般的なケースでは、上記で説明したよりも少し複雑です。省略形の割り当ては、実際にはと同等です

__some_temporary = type(self)()
value = __some_temporary
self[key] = __some_temporary

単純化された形式は、が単純なローカル変数であるvalue = type(self)(); self[key] = valueためにのみ発生します。失敗する可能性のある形式の式に置き換えられたvalue場合、同等性は保持されなくなります。valuecontainer[key]

于 2013-02-27T22:04:02.417 に答える
1

単なる構文です。コードが読みやすくなる場合もあれば、そうでない場合もあります。

しかし、どうなりますか?他の答えは私を興味深くさせました:私はそれに、compierがおそらく「レジスタまたは変数」を使用しているとコメントしました、そしてそれはまさに起こることです。簡単な関数を逆コンパイルしてみましょう。

>>> import dis
>>> def f():
...     a = b = c = 1
...     return a
... 
>>> dis.dis(f)
  2           0 LOAD_CONST               1 (1)
              3 DUP_TOP             
              4 STORE_FAST               0 (a)
              7 DUP_TOP             
              8 STORE_FAST               1 (b)
             11 STORE_FAST               2 (c)

  3          14 LOAD_FAST                0 (a)
             17 RETURN_VALUE        

右端の値(type(self)()実際の場合は1)がスタックにロードされ(「ローカル変数」と考えてください)、スタックに複製されます(スタックベースのVM操作ではスタックを消費するため、「 「複数のコピーを作成するために必要な値)、割り当て、複製、割り当てなど。つまり、Pythonに変換して戻すと、次のようになります。

def f():
    t = 1
    a = t
    b = t
    c = t
    return a

コンパイラーは、左から右への割り当ての順序(a、b、c)も保持します。

于 2013-02-27T22:01:08.407 に答える