Respostas:
in
é definitivamente mais pitônico.
Na verdade has_key()
foi removido em Python 3.x .
keys()
é apenas uma visualização de conjunto em um dicionário, em vez de uma cópia, assim x in d.keys()
como O (1). Ainda assim, x in d
é mais pitônico.
x in d.keys()
deve construir e destruir um objeto temporário, completo com a alocação de memória que implica, onde x in d.keys()
está apenas fazendo uma operação aritmética (calculando o hash) e fazendo uma pesquisa. Observe que d.keys()
é apenas cerca de 10 vezes maior que isso, o que ainda não é muito longo. Eu não verifiquei, mas ainda tenho certeza de que é apenas O (1).
in
ganha de mãos para baixo, não apenas em elegância (e não sendo depreciada ;-) mas também em desempenho, por exemplo:
$ python -mtimeit -s'd=dict.fromkeys(range(99))' '12 in d'
10000000 loops, best of 3: 0.0983 usec per loop
$ python -mtimeit -s'd=dict.fromkeys(range(99))' 'd.has_key(12)'
1000000 loops, best of 3: 0.21 usec per loop
Embora a seguinte observação nem sempre seja verdadeira, você notará que , geralmente , em Python, a solução mais rápida é mais elegante e pitônica; é por isso que -mtimeit
é tão útil - não se trata apenas de economizar cem nanossegundos aqui e ali! -)
has_key
parece ser O (1) também.
De acordo com a documentação do python :
has_key()
foi descontinuado em favor dekey in d
.
has_key()
foi removido no Python 3
Use dict.has_key()
se (e somente se) for necessário que seu código seja executável pelas versões do Python anteriores à 2.3 (quando key in dict
foi introduzido).
Há um exemplo em que in
realmente mata seu desempenho.
Se você usar in
em um O (1) recipiente que apenas implementos __getitem__
e has_key()
, mas não __contains__
você vai virar um O (1) procurar em uma pesquisa O (N) (como in
cai de volta para uma busca linear via __getitem__
).
A correção é obviamente trivial:
def __contains__(self, x):
return self.has_key(x)
has_key()
é específico para dicionários Python 2 . in
/ __contains__
é a API correta a ser usada; para aqueles recipientes onde uma varredura completa é inevitável não há nenhum has_key()
método de qualquer maneira , e se há um O (1) abordagem, em seguida, que vai ser de caso de uso específico e assim até o desenvolvedor para escolher o tipo de dados correto para o problema.
has_key
é um método de dicionário, mas in
funcionará em qualquer coleção e, mesmo quando __contains__
estiver ausente, in
usará qualquer outro método para iterar a coleção e descobrir.
in
testes em range
objetos. Não tenho tanta certeza sobre sua eficiência no Python 2 xrange
. ;)
__contains__
pode calcular trivialmente se um valor está no intervalo ou não.
range
instância a cada vez. Usando uma instância única e preexistente, o teste "número inteiro no intervalo" é cerca de 40% mais rápido nos meus tempos.
A solução para dict.has_key () está obsoleta, use 'in' - sublime text editor 3
Aqui eu peguei um exemplo de dicionário chamado 'idades' -
ages = {}
# Add a couple of names to the dictionary
ages['Sue'] = 23
ages['Peter'] = 19
ages['Andrew'] = 78
ages['Karren'] = 45
# use of 'in' in if condition instead of function_name.has_key(key-name).
if 'Sue' in ages:
print "Sue is in the dictionary. She is", ages['Sue'], "years old"
else:
print "Sue is not in the dictionary"
Expandindo os testes de desempenho de Alex Martelli com os comentários de Adam Parkin ...
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 301, in main
x = t.timeit(number)
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
d.has_key(12)
AttributeError: 'dict' object has no attribute 'has_key'
$ python2.7 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0872 usec per loop
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(1999))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0858 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d'
10000000 loops, best of 3: 0.031 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d'
10000000 loops, best of 3: 0.033 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d.keys()'
10000000 loops, best of 3: 0.115 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d.keys()'
10000000 loops, best of 3: 0.117 usec per loop
Se você tem algo parecido com isto:
t.has_key(ew)
altere para abaixo para rodar no Python 3.X e acima:
key = ew
if key not in t
t.has_key(ew)
retorna True
se as ew
referências de valor também são uma chave no dicionário. key not in t
retorna True
se o valor for nãono dicionário. Além disso, okey = ew
alias é muito, muito redundante. A ortografia correta éif ew in t
. Qual é o que a resposta aceita de 8 anos antes já lhe disse.