Verschil tussen dict.clear() en het toewijzen van {} in Python

Is er in Python een verschil tussen het aanroepen van clear()en het toewijzen van {}aan een woordenboek? Zo ja, wat is het?
Voorbeeld:

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


Antwoord 1, autoriteit 100%

Als je een andere variabele hebt die ook naar hetzelfde woordenboek verwijst, is er een groot verschil:

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

Dit komt doordat het toewijzen van d = {}een nieuw, leeg woordenboek creëert en dit toewijst aan de variabele d. Dit laat d2wijzen naar het oude woordenboek met items er nog in. d.clear()wist echter hetzelfde woordenboek waar den d2beide naar verwijzen.


Antwoord 2, autoriteit 11%

d = {}zal een nieuwe instantie maken voor dmaar alle andere verwijzingen zullen nog steeds naar de oude inhoud verwijzen.
d.clear()zal de inhoud resetten, maar alle verwijzingen naar dezelfde instantie zullen nog steeds correct zijn.


Antwoord 3, autoriteit 7%

Naast de verschillen die in andere antwoorden worden genoemd, is er ook een snelheidsverschil. d = {} is meer dan twee keer zo snel:

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

Antwoord 4, autoriteit 3%

Ter illustratie voor de dingen die al eerder zijn genoemd:

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

Antwoord 5, autoriteit 2%

Naast het antwoord van @odano, lijkt het gebruik van d.clear()sneller als je het dictaat meerdere keren wilt wissen.

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)

Het resultaat is:

20.0367929935
19.6444659233

Antwoord 6, autoriteit 2%

Mutatie-methoden zijn altijd handig als het oorspronkelijke object niet binnen het bereik valt:

def fun(d):
    d.clear()
    d["b"] = 2
d={"a": 2}
fun(d)
d          # {'b': 2}

Het opnieuw toewijzen van het woordenboek zou een nieuw object creëren en zou het originele niet wijzigen.


Antwoord 7

Eén ding dat niet wordt genoemd, zijn scopingproblemen. Geen goed voorbeeld, maar dit is het geval waarin ik het probleem tegenkwam:

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

De oplossing is om c_kwargs = {}te vervangen door c_kwargs.clear()

Als iemand een praktischer voorbeeld bedenkt, kun je dit bericht bewerken.


Antwoord 8

Bovendien kan de dict-instantie soms een subklasse van dict zijn (bijvoorbeeld defaultdict). In dat geval heeft het gebruik van clearde voorkeur, omdat we het exacte type van het dictaat niet hoeven te onthouden en ook dubbele code moeten vermijden (koppeling van de clearingregel met de initialisatieregel).

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

Other episodes