web-dev-qa-db-fra.com

Le moyen le plus pythonique de vérifier si une valeur dans un dictionnaire est définie/a une longueur nulle

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

19
Adam Parkin

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.

21
Ethan Furman
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.

13
phihag

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.

3
Nathan

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.

3
Nate

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.

1
oivvio

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:

  1. Utilisez mydict.get. Vous devriez utiliser ceci si la clé peut être ou ne pas être dans le dictionnaire.
  2. Utilisez mydict[key]. Vous devriez l'utiliser si vous êtes certain que la clé que vous voulez est dans le dict.
  3. Utilisez 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.
0
Robin

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]))
0
Safvan CK

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])
0
Steven Rumbalski