web-dev-qa-db-fra.com

python - vérifier si une valeur de dict n'est pas None (sans itérateurs)

Je me demande s'il est possible d'obtenir la même sortie qu'à partir de ce code:

d = {'a':None,'b':'12345','c':None}
nones=False
for k,v in d.items(): 
  if d[k] is None:
    nones=True      

ou

any([v==None for v in d.values()])

mais sans itérateur de boucle for, ni générateur?

19
yourstruly

Vous pouvez utiliser

nones = not all(d.values())

Si toutes les valeurs ne sont pas None, nones serait défini sur False, sinon True. Ce n'est qu'une abstraction, mais en interne, elle doit parcourir la liste de valeurs.

10
hspandher

Vous pourriez avoir Python faire le bouclage en code C en utilisant un vue dictionnaire ; cela fait un test d'appartenance par rapport à toutes les valeurs sans créer de nouvelle liste:

if None not in d.viewvalues():

Dans Python 3, dict.values() renvoie également une vue de dictionnaire.

Démo sur Python 2:

>>> d = {'a': None, 'c': None, 'b': '12345'}
>>> None not in d.viewvalues()
False

Cela fera une boucle sur les valeurs jusqu'à ce qu'une correspondance soit trouvée, tout comme l'appartenance à une liste ou un test any() approprié, ce qui en fait un test O(N). Cela diffère d'un dictionnaire ou définir un test d'adhésion, où le hachage peut être utilisé pour vous donner un test de coût fixe en moyenne.

Vous n'utilisiez pas correctement any(); supprimez les crochets [...]:

if any(v is not None for v in d.itervalues()):  # Python 3: use d.values()

Si votre objectif est de tester certaines valeurs, et vous devez éviter une boucle constante pour chaque test, envisagez plutôt de créer un index inverse:

inverse_index = {}
for key, value in d.items():
    inverse.setdefault(value, set()).add(key)

Cela nécessite cependant que les valeurs soient lavables. Vous pouvez maintenant simplement tester chaque valeur:

if None not in inverse_index:

en O(1) fois.

7
Martijn Pieters