web-dev-qa-db-fra.com

pas Aucun test dans Python

Parmi ces tests, aucun n'est.

if val != None:

if not (val is None):

if val is not None:

Lequel est préférable et pourquoi?

607
prosseek
if val is not None:
    # ...

est l'idiome Pythonic pour tester qu'une variable n'est pas définie sur None. Cet idiome a des utilisations particulières dans le cas de déclaration de fonctions de mot clé avec des paramètres par défaut . is teste l'identité en Python. Comme il n'y a qu'une seule et unique instance de None présente dans un script/programme Python en cours d'exécution, is en est le test optimal. Comme indique Johnsyweb , cela est décrit dans PEP 8 sous "Recommandations de programmation".

Quant à savoir pourquoi cela est préféré à

if not (val is None):
    # ...

cela fait simplement partie du Zen of Python : "La lisibilité compte." Bon Python est souvent proche de bon pseudocode .

872
gotgenes

De, Recommandations de programmation, PEP 8 :

Les comparaisons avec des singletons comme Aucune ne devraient toujours se faire avec "est" ou "n'est pas", jamais les opérateurs d'égalité.

Aussi, méfiez-vous de l'écriture "si x" lorsque vous voulez vraiment dire "si x n'est pas Aucun" - par ex. lors du test si une variable ou un argument dont la valeur par défaut est Aucun a été défini sur une autre valeur. L'autre valeur peut avoir un type (tel qu'un conteneur) qui peut être faux dans un contexte booléen!

PEP 8 est une lecture essentielle pour tout programmeur Python.

95
Johnsyweb

L'une ou l'autre de ces deux dernières, puisque val pourrait potentiellement être d'un type définissant __eq__() pour qu'il retourne la valeur true lorsqu'il est passé None.

22

La meilleure solution avec ce type de questions est de voir exactement ce que fait python. Le module dis est incroyablement informatif:

>>> def f(val):
...   if val != None:
...     return True
...   return False
...
>>> def g(val):
...   if not (val is None):
...     return True
...   return False
...
>>> def h(val):
...   if val is not None:
...     return True
...   return False
...
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               3 (!=)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE
>>> dis.dis(h)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE

Notez que les deux derniers cas se réduisent à la même séquence d'opérations (python lit not (val is None) et utilise l'opérateur is not.). Le premier utilise l'opérateur != lors de la comparaison avec None.

Comme le soulignent d'autres réponses, utiliser != pour comparer avec None est une mauvaise idée.

17
SheetJS