Réponses:
in
est définitivement plus pythonique.
En fait has_key()
a été supprimé dans 3.x Python .
keys()
c'est juste une vue d'ensemble dans un dictionnaire plutôt qu'une copie, tout x in d.keys()
comme O (1). Pourtant, x in d
c'est plus Pythonic.
x in d.keys()
doit construire et détruire un objet temporaire, avec l'allocation de mémoire qui en découle, où x in d.keys()
fait juste une opération arithmétique (calcul du hachage) et fait une recherche. Notez que ce d.keys()
n'est que 10 fois plus long que cela, ce qui n'est pas vraiment long. Je n'ai pas vérifié mais je suis toujours sûr que ce n'est que O (1).
in
gagne haut la main, non seulement en élégance (et en n'étant pas déprécié ;-) mais aussi en performance, par exemple:
$ 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
Bien que l'observation suivante ne soit pas toujours vraie, vous remarquerez qu'en général , en Python, la solution la plus rapide est plus élégante et Pythonique; c'est pourquoi -mtimeit
est si utile - il ne s'agit pas seulement d'économiser une centaine de nanosecondes ici et là! -)
has_key
semble être O (1) aussi.
Selon les documents python :
has_key()
est déconseillé en faveur dekey in d
.
has_key()
est maintenant supprimé dans Python 3
Utilisez dict.has_key()
si (et seulement si) votre code doit être exécutable par les versions Python antérieures à 2.3 (lors de key in dict
son introduction).
Il y a un exemple où in
tue réellement votre performance.
Si vous utilisez in
sur un conteneur O (1) qui implémente uniquement __getitem__
et has_key()
non, __contains__
vous transformerez une recherche O (1) en recherche O (N) (comme cela in
revient à une recherche linéaire via __getitem__
).
Le correctif est évidemment trivial:
def __contains__(self, x):
return self.has_key(x)
has_key()
est spécifique aux dictionnaires Python 2 . in
/ __contains__
est la bonne API à utiliser; pour les conteneurs où une analyse complète est inévitable, il n'y a de toute façon pas de has_key()
méthode , et s'il existe une approche O (1), ce sera spécifique au cas d'utilisation et donc au développeur de choisir le bon type de données pour le problème.
has_key
est une méthode de dictionnaire, mais in
fonctionnera sur n'importe quelle collection, et même lorsqu'elle __contains__
est manquante, in
utilisera toute autre méthode pour itérer la collection pour le découvrir.
in
tests sur des range
objets. xrange
Cependant, je ne suis pas sûr de son efficacité sur Python 2 . ;)
__contains__
peut trivialement calculer si une valeur est dans la plage ou non.
range
instance à chaque fois. En utilisant une seule instance préexistante , le test "nombre entier dans la plage" est environ 40% plus rapide dans mes délais.
La solution à dict.has_key () est déconseillée, utilisez 'in' - sublime text editor 3
Ici, j'ai pris un exemple de dictionnaire nommé «âges» -
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"
Développant les tests de performance d'Alex Martelli avec les commentaires d'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 vous avez quelque chose comme ça:
t.has_key(ew)
changez-le ci-dessous pour fonctionner sur Python 3.X et supérieur:
key = ew
if key not in t
t.has_key(ew)
renvoie True
si la ew
référence des valeurs est également une clé dans le dictionnaire. key not in t
renvoie True
si la valeur n'est pas dans le dictionnaire. De plus, l' key = ew
alias est très, très redondant. L'orthographe correcte est if ew in t
. C'est ce que la réponse acceptée de 8 ans auparavant vous a déjà dit.