Чи існує різниця між викликом clear()
та призначенням {}
словника у python ? Якщо так, що це? Приклад:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Чи існує різниця між викликом clear()
та призначенням {}
словника у python ? Якщо так, що це? Приклад:
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 = {} швидше вдвічі:
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
d = {}
має бути швидшим, оскільки очищення цілого можна залишити в Garbage Collector на потім.
На додаток до відповіді @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
Методи мутації завжди корисні, якщо оригінальний об'єкт не входить у сферу застосування:
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()
Якщо хтось придумає більш практичний приклад, сміливо редагуйте цю публікацію.
global c_kwargs
мабуть, теж працюватиме ні? Хоча, мабуть, global
це не найкраще, чим можна користуватися.
global
ця функція поводиться по-різному - усі виклики conf_decorator будуть спільно використовувати ту саму змінну c_kwargs. Я вважаю, що Python 3 додав nonlocal
ключове слово для вирішення цієї проблеми, і це спрацювало б.
Крім того, іноді екземпляр dict може бути підкласом dict ( defaultdict
наприклад). У цьому випадку використання clear
є кращим, оскільки нам не потрібно пам’ятати точний тип дикту, а також уникати дублювання коду (з’єднання лінії очищення з лінією ініціалізації).
x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)