Respuestas:
in
Definitivamente es más pitónico.
De hecho has_key()
fue eliminado en Python 3.x .
keys()
es solo una vista de conjunto en un diccionario en lugar de una copia, también lo x in d.keys()
es O (1). Aún así, x in d
es más pitónico.
x in d.keys()
debe construir y destruir un objeto temporal, completo con la asignación de memoria que conlleva, donde x in d.keys()
solo está haciendo una operación aritmética (calculando el hash) y haciendo una búsqueda. Tenga en cuenta que d.keys()
solo es aproximadamente 10 veces más largo que esto, que todavía no es realmente largo. No lo he verificado, pero todavía estoy bastante seguro de que es solo O (1).
in
gana sin dudas, no solo en elegancia (y no en desuso ;-) sino también en rendimiento, por ejemplo:
$ 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
Si bien la siguiente observación no siempre es cierta, notará que , por lo general , en Python, la solución más rápida es más elegante y pitónica; por eso -mtimeit
es TAN útil: ¡no se trata solo de ahorrar cien nanosegundos aquí y allá!)
has_key
parece ser O (1) también.
Según los documentos de Python :
has_key()
está en desuso a favor dekey in d
.
has_key()
ahora se elimina en Python 3
Use dict.has_key()
si (y solo si) se requiere que su código sea ejecutable por versiones de Python anteriores a la 2.3 (cuando key in dict
se introdujo).
Hay un ejemplo donde in
realmente mata tu rendimiento.
Si lo usa in
en un contenedor O (1) que solo implementa __getitem__
y has_key()
no __contains__
lo hará, convertirá una búsqueda O (1) en una búsqueda O (N) (ya que in
retrocede a una búsqueda lineal a través de__getitem__
).
La solución es obviamente trivial:
def __contains__(self, x):
return self.has_key(x)
has_key()
es específico de los diccionarios Python 2 . in
/ __contains__
es la API correcta para usar; para aquellos contenedores en los que es inevitable una exploración completa, no hay ningún has_key()
método de todos modos , y si hay un enfoque O (1), entonces ese será el caso de uso específico y el desarrollador debe elegir el tipo de datos correcto para el problema.
has_key
es un método de diccionario, pero in
funcionará en cualquier colección, e incluso cuando __contains__
falte, in
usará cualquier otro método para iterar la colección para averiguarlo.
in
pruebas en range
objetos. Sin embargo, no estoy tan seguro de su eficacia en Python 2 xrange
. ;)
__contains__
puede calcular trivialmente si un valor está en el rango o no.
range
instancia cada vez. Usando una sola instancia preexistente, la prueba de "entero en el rango" es aproximadamente un 40% más rápida en mis tiempos.
La solución a dict.has_key () está en desuso, use 'in' - sublime text editor 3
Aquí he tomado un ejemplo de diccionario llamado 'edades':
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"
Ampliando las pruebas de rendimiento de Alex Martelli con los comentarios 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
Si tienes algo como esto:
t.has_key(ew)
cámbielo a continuación para ejecutarlo en Python 3.X y superior:
key = ew
if key not in t
t.has_key(ew)
devuelve True
si el valor de ew
referencia también es una clave en el diccionario. key not in t
devuelve True
si el valor no está en el diccionario. Además, el key = ew
alias es muy, muy redundante. La ortografía correcta es if ew in t
. Que es lo que la respuesta aceptada de 8 años antes ya le dijo.