В python существует ли разница между вызовом clear()
и назначением {}
словаря? Если да, что это?
Пример:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
В python существует ли разница между вызовом clear()
и назначением {}
словаря? Если да, что это?
Пример:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Если у вас есть другая переменная, относящаяся к одному и тому же словарю, есть большая разница:
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}
Это связано с тем, что назначение d = {}
создает новый пустой словарь и присваивает его переменной d
. Это приводит к тому, что d2
указывает на старый словарь с элементами, находящимися в нем. Однако d.clear()
очищает тот же словарь, что d
и d2
обе указывают на.
d = {}
создаст новый экземпляр для d
, но все остальные ссылки будут по-прежнему указывать на старое содержимое.
d.clear()
будет reset содержимое, но все ссылки на один и тот же экземпляр будут по-прежнему правильными.
В дополнение к различиям, упомянутым в других ответах, также существует разница в скорости. d = {} более чем вдвое быстрее:
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
В дополнение к ответу @odano кажется, что использование d.clear()
выполняется быстрее, если вы хотите очистить dict в течение многих раз.
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
В качестве иллюстрации для уже упомянутых вещей:
>>> a = {1:2}
>>> id(a)
3073677212L
>>> a.clear()
>>> id(a)
3073677212L
>>> a = {}
>>> id(a)
3073675716L
Методы мутирования всегда полезны, если исходный объект не находится в области видимости:
def fun(d):
d.clear()
d["b"] = 2
d={"a": 2}
fun(d)
d # {'b': 2}
Повторное присвоение словаря создаст новый объект и не будет изменять исходный.
Одна вещь, о которой не упоминается, - это проблемы, связанные с определением области. Не очень хороший пример, но вот случай, когда я столкнулся с проблемой:
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()
Если кто-то придумает более практичный пример, не стесняйтесь редактировать этот пост.
Кроме того, иногда экземпляр dict может быть подклассом dict (defaultdict
например). В этом случае предпочтительнее использовать clear
, так как нам не нужно помнить точный тип dict, а также избегать дублирования кода (соединение линии очистки с линией инициализации).
x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)