Em python, existe uma diferença entre chamar clear()
e atribuir {}
a um dicionário? Se sim, o que é isso? Exemplo:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Em python, existe uma diferença entre chamar clear()
e atribuir {}
a um dicionário? Se sim, o que é isso? Exemplo:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Respostas:
Se você tiver outra variável também se referindo ao mesmo dicionário, há uma grande diferença:
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}
Isso ocorre porque a atribuição d = {}
cria um novo dicionário vazio e o atribui à d
variável. Isso deixa d2
apontar para o dicionário antigo com itens ainda nele. No entanto, d.clear()
limpa o mesmo dicionário que d
e d2
ambos apontam para.
Além das diferenças mencionadas em outras respostas, também há uma diferença de velocidade. d = {} é duas vezes mais rápido:
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 = {}
deve ser mais rápida, pois a limpeza de todo pode ser deixada para o Garbage Collector para mais tarde.
Como ilustração para as coisas já mencionadas anteriormente:
>>> a = {1:2}
>>> id(a)
3073677212L
>>> a.clear()
>>> id(a)
3073677212L
>>> a = {}
>>> id(a)
3073675716L
.clear
modifica o objeto, mas `= {}` cria um novo objeto.
Além da resposta do @odano, parece que o uso d.clear()
é mais rápido se você quiser limpar o ditado por muitas vezes.
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)
O resultado é:
20.0367929935
19.6444659233
Os métodos de mutação são sempre úteis se o objeto original não estiver no escopo:
def fun(d):
d.clear()
d["b"] = 2
d={"a": 2}
fun(d)
d # {'b': 2}
Reatribuir o dicionário criaria um novo objeto e não modificaria o original.
Uma coisa não mencionada são os problemas de escopo. Não é um ótimo exemplo, mas aqui está o caso em que me deparei com o problema:
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
A solução é substituir c_kwargs = {}
porc_kwargs.clear()
Se alguém pensar em um exemplo mais prático, fique à vontade para editar esta postagem.
global c_kwargs
provavelmente também funcionaria não? Embora provavelmente global
não seja a melhor coisa para se usar muito.
global
faria a função se comportar de maneira diferente - todas as chamadas para conf_decorator compartilhariam a mesma variável c_kwargs. Acredito que o Python 3 adicionou a nonlocal
palavra-chave para resolver esse problema, e isso funcionaria.
Além disso, às vezes a instância dict pode ser uma subclasse de dict ( defaultdict
por exemplo). Nesse caso, clear
é preferível usar , pois não precisamos lembrar o tipo exato do ditado e também evitar código duplicado (acoplando a linha de limpeza com a linha de inicialização).
x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)