Supposons que j'ai un dictionnaire et que je veuille vérifier si une clé est associée à une valeur non vide. Une des façons de faire serait la fonction len:
mydict = {"key" : "value", "emptykey" : ""}
print "True" if len(mydict["key"]) > 0 else "False" # prints true
print "True" if len(mydict["emptykey"]) > 0 else "False" # prints false
Cependant, on peut s’appuyer sur la sémantique de Python et savoir si un objet est défini, il vaut true et laisse de côté l’appel len:
mydict = {"key" : "value", "emptykey" : ""}
print "True" if mydict["key"] else "False" # prints true
print "True" if mydict["emptykey"] else "False" # prints false
Cependant, je ne suis pas sûr de ce qui est le plus Pythonic. Le premier a le sentiment que "explicite vaut mieux qu'implicite", alors que le second estime que "simple vaut mieux que complexe".
Je me demande également si le fait de laisser tomber l'appel à len pourrait me piquer, car le dict avec lequel je travaille ne contient pas nécessairement de chaînes, mais pourrait contenir d'autres types de caractères (listes, ensembles, etc.). OTOH, dans l'ancien (avec l'appel len) si None est stocké en tant que valeur, le code explose, alors que la version non-len fonctionnera comme prévu (sera évalué à false).
Quelle version est la plus sûre et la plus pythonique?
Edit: clarifier les hypothèses: I know la clé est dans le dictionnaire, et je sais que les valeurs seront len-possible. Je ne peux pas non plus éviter d'avoir des valeurs de longueur nulle dans le dictionnaire.
Edit # 2: Il semble que les gens manquent le point de ma question. Je ne cherche pas à déterminer le moyen le plus sûr/pythonique de vérifier si une clé est présente dans un dictionnaire, j'essaie de vérifier si une valeur a une longueur nulle ou non
Si vous savez que la clé est dans le dictionnaire, utilisez
if mydict["key"]:
...
Il est simple, facile à lire et dit: "si la valeur liée à 'clé' est évaluée à True
, faites quelque chose". Il est important de savoir que les types de conteneur (dict, list, tuple, str, etc.) ne sont évalués qu'à True
si leur len
est supérieur à 0.
Cela déclenchera également une KeyError
si votre principe selon lequel une clé est dans mydict
est violé.
Tout cela le rend pythonique.
print (bool(mydict.get('key')))
ou, dans une déclaration if:
print ('True' if mydict.get('key') else 'False')
Si la valeur absente est un cas d’erreur (c’est-à-dire que vous vous attendez à ce qu’elle soit là), vous devez choisir la solution n ° 2, c’est-à-dire.
print ('True' if mydict['key'] else 'False')
Cela permet à mydict['key']
de choisir la définition la plus efficace pour être vide. Pour certains objets (tels que ceux en grappes), déterminer la longueur réelle est une opération assez compliquée, alors qu'il est simple de déterminer si l'objet est vide ou non.
Vous pouvez également comparer à ''
, c’est-à-dire mydict['key'] == ''
, pour que votre expression soit parfaitement claire. Utiliser len
fonctionne, mais n’est pas aussi intuitif.
En résumé, laissez à l'objet testé le soin de définir s'il est vide ou non et lancez-le simplement pour le bool.
J'utiliserais une variante de la première option:
>>> mydict = {"key" : "value", "emptykey" : ""}
>>> print bool(mydict["key"])
True
>>> print bool(mydict["emptykey"])
False
Toute classe qui fournit __len__
peut être convertie directement en un booléen (voir Test de valeur de vérité ), de sorte que bool(container)
est équivalent à bool(len(container))
. Une longueur de 0 deviendra le booléen False
tandis que toutes les autres longueurs seront True
. Vous n'aurez jamais d'objet de longueur négative. De plus, les valeurs booléennes True
et False
peuvent être imprimées directement via print
, de sorte que vous n’avez pas besoin du conditionnel.
De ici :
Dans le contexte des opérations booléennes, et également lorsque des expressions sont utilisées par des instructions de flux de contrôle, les valeurs suivantes sont interprétées comme étant fausses:
False
,None
, zéro numérique de tous les types et chaînes et conteneurs vides (y compris des chaînes, des n-uplets, des listes, des dictionnaires , ensembles et frozensets). Toutes les autres valeurs sont interprétées comme vraies.
Je pense qu'il est prudent de dire que l'évaluation directe est votre meilleure option - bien que, comme @phihag l'a dit, il soit plus sûr d'utiliser get
à la place, car cela vous protégera d'une KeyError
.
Le titre et la première phrase expriment en réalité deux questions légèrement différentes.
Pour la question du titre
Le moyen le plus pythonique de vérifier si une valeur dans un dictionnaire est définie
J'irais avec
"key" in mydict
et pour la deuxième question
Supposons que j'ai un dictionnaire et que je veuille vérifier si une clé est associée à une valeur non vide.
J'irais avec
"key" in mydict and bool(mydict["key"])
La première partie vérifie la présence de "key" dans mydict et la seconde renvoie true pour toutes les valeurs de "key" autres que False, None, la chaîne vide, le dictionnaire vide, la liste vide et 0.
La manière la plus pythonique serait de ne pas définir la valeur indéfinie (bien que son utilisation dépende de l'utilisation que vous en faites) et d'utiliser in
:
mydict = {"key" : "value"}
print "True" if "key" in mydict else "False" # prints true
print "True" if "emptykey" in mydict else "False" # prints false
Sinon, vous avez trois options:
mydict.get
. Vous devriez utiliser ceci si la clé peut être ou ne pas être dans le dictionnaire.mydict[key]
. Vous devriez l'utiliser si vous êtes certain que la clé que vous voulez est dans le dict.len(mydict[key]) > 0
. Cela ne fonctionne que si la valeur est définie par __len__
. Habituellement, la valeur de vérité d'une valeur de conteneur dépend de toute façon du __len__
, les solutions ci-dessus sont donc préférables.Vous pouvez simplement vérifier que toute valeur dans le dict est de longueur nulle ou non en:
# To get keys which having zero length value:
keys_list = [key for key,val in mydict.items() if not val]
# To check whether the dict has any zero length value in it (returns True or False):
any_empty_vals = bool(len(['' for x in data_dict.values() if not x]))
De vos deux exemples, je préfère le second.
Cependant, je déconseille de stocker les clés vides. De plus, un defaultdict fonctionnerait bien ici:
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d[1].append(1)
>>> 1 in d
True
Si vous devez stocker des clés vides, vous n'avez pas besoin des valeurs de chaîne "True"
et "False"
. Faites juste ceci:
print bool(mydict[key])