web-dev-qa-db-ja.com

dict.clear()とPythonの{}の割り当ての違い

Pythonでは、clear()の呼び出しと{}の辞書への割り当てに違いはありますか?はいの場合、それは何ですか?例:

d = {"stuff":"things"}
d.clear()   #this way
d = {}      #vs this way
155
Marcin

同じ辞書も参照している別の変数がある場合、大きな違いがあります。

>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}

これは、d = {}を割り当てると、新しい空の辞書が作成され、d変数に割り当てられるためです。これにより、d2は、アイテムがまだ残っている古い辞書を指しています。ただし、d.clear()は、dd2の両方が指す同じ辞書をクリアします。

266
Greg Hewgill

d = {}dの新しいインスタンスを作成しますが、他のすべての参照は引き続き古いコンテンツを指します。 d.clear()は内容をリセットしますが、同じインスタンスへのすべての参照は依然として正しいです。

29
Michel

他の回答で言及された違いに加えて、速度の違いもあります。 d = {}は2倍以上高速です。

python -m timeit -s "d = {}" "for i in xrange(500000): d.clear()"
10 loops, best of 3: 127 msec per loop

python -m timeit -s "d = {}" "for i in xrange(500000): d = {}"
10 loops, best of 3: 53.6 msec per loop
21
odano

@odanoの答えに加えて、辞書を何度もクリアしたい場合は、d.clear()を使用する方が速いようです。

import timeit

p1 = ''' 
d = {}
for i in xrange(1000):
    d[i] = i * i
for j in xrange(100):
    d = {}
    for i in xrange(1000):
        d[i] = i * i
'''

p2 = ''' 
d = {}
for i in xrange(1000):
    d[i] = i * i
for j in xrange(100):
    d.clear()
    for i in xrange(1000):
        d[i] = i * i
'''

print timeit.timeit(p1, number=1000)
print timeit.timeit(p2, number=1000)

結果は次のとおりです。

20.0367929935
19.6444659233
7
lastland

Mutatingメソッドは、元のオブジェクトがスコープ内にない場合に常に役立ちます。

def fun(d):
    d.clear()
    d["b"] = 2

d={"a": 2}
fun(d)
d          # {'b': 2}

辞書を再割り当てすると、新しいオブジェクトが作成され、元のオブジェクトは変更されません。

7
Karoly Horvath

すでに前述したことの例として:

>>> a = {1:2}
>>> id(a)
3073677212L
>>> a.clear()
>>> id(a)
3073677212L
>>> a = {}
>>> id(a)
3073675716L
7
maxp

言及されていないことの1つは、スコープの問題です。良い例ではありませんが、私が問題に遭遇した場合は次のとおりです。

def conf_decorator(dec):
    """Enables behavior like this:
        @threaded
        def f(): ...

        or

        @threaded(thread=KThread)
        def f(): ...

        (assuming threaded is wrapped with this function.)
        Sends any accumulated kwargs to threaded.
        """
    c_kwargs = {}
    @wraps(dec)
    def wrapped(f=None, **kwargs):
        if f:
            r = dec(f, **c_kwargs)
            c_kwargs = {}
            return r
        else:
            c_kwargs.update(kwargs) #<- UnboundLocalError: local variable 'c_kwargs' referenced before assignment
            return wrapped
    return wrapped

解決策は、c_kwargs = {}c_kwargs.clear()に置き換えることです

誰かがより実用的な例を考えているなら、この投稿を自由に編集してください。

4
Ponkadoodle

また、dictインスタンスはdictのサブクラスである場合があります(たとえば、defaultdict)。その場合は、clearを使用することをお勧めします。これは、dictの正確なタイプを覚える必要がなく、重複コード(クリアラインと初期化ラインを結合する)も避ける必要があるためです。

x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)
1
Tzach