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?
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 .
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.
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
.
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.