J'ai toujours pensé que la version if not x is None
était plus claire, mais le guide de style de Google et PEP-8 utilisent tous deux if x is not None
. Existe-t-il une différence de performance mineure (je suppose que non) et existe-t-il un cas où l'une ne convient pas (faisant de l'autre un vainqueur évident de mon congrès)? *
* Je parle de n'importe quel singleton, plutôt que de simplement None
.
... pour comparer des singletons comme aucun. L'utilisation est ou n'est pas.
Il n'y a pas de différence de performances, car ils compilent dans le même bytecode:
Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
... return x is not None
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 0 (None)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
>>> def g(x):
... return not x is None
...
>>> dis.dis(g)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 0 (None)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
Stylistiquement, j'essaie d'éviter not x is y
. Bien que le compilateur la traite toujours comme not (x is y)
, un lecteur humain pourrait mal comprendre la construction en tant que (not x) is y
. Si j'écris x is not y
alors il n'y a pas d'ambiguïté.
Le guide de style de Google et Python est la meilleure pratique:
if x is not None:
# Do something about x
L'utilisation de not x
peut entraîner des résultats indésirables. Voir ci-dessous:
>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0] # You don't want to fall in this one.
>>> not x
False
Vous pourriez être intéressé de voir quels littéraux sont évalués à True
ou False
en Python:
Modifier pour commentaire ci-dessous:
Je viens de faire quelques tests supplémentaires. not x is None
n'annule pas d'abord x
puis comparé à None
. En fait, il semble que l'opérateur is
ait une priorité plus élevée lorsqu'il est utilisé de cette façon:
>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False
Par conséquent, not x is None
est, à mon avis honnête, préférable d'éviter.
Plus d'édition:
Je viens de faire plus de tests et peux confirmer que le commentaire de bukzor est correct. (Au moins, je n'ai pas pu le prouver.)
Cela signifie que if x is not None
a le résultat exact sous la forme if not x is None
. Je me suis trompé. Merci bukzor.
Cependant, ma réponse est toujours valable: Utilisez le conventionnel if x is not None
. :]
Le code doit être écrit pour être compréhensible par le programmeur d’abord, puis par le compilateur ou l’interprète. La construction "is not" ressemble plus à l'anglais que "not is".
La réponse est plus simple que ce que les gens font.
Il n'y a aucun avantage technique dans les deux cas, et "x n'est pas y" est ce que tout le monde utilise, ce qui en fait clairement le gagnant. Peu importe qu'il "ressemble plus à l'anglais" ou non; tout le monde l'utilise, ce qui signifie que chaque utilisateur de Python - même les utilisateurs chinois, dont le langage Python ne ressemble à rien - le comprendra d'un coup d'œil, où la syntaxe légèrement moins commune prendra deux cycles cérébraux supplémentaires à analyser .
Ne soyez pas différent juste pour être différent, au moins dans ce domaine.
Python
if x is not None
ouif not x is None
?
TLDR: Le compilateur de bytecode les analyse tous les deux comme x is not None
- donc pour des raisons de lisibilité, utilisez if x is not None
.
Nous utilisons Python parce que nous attachons une grande importance à la lisibilité humaine, à la facilité d'utilisation et à la correction de divers paradigmes de programmation par rapport aux performances.
Python optimise la lisibilité, en particulier dans ce contexte.
La not
se lie plus faiblement que is
, il n'y a donc pas de différence logique ici. Voir le documentation :
Les opérateurs
is
etis not
testent l'identité de l'objet:x is y
est vrai si et seulement si x et y sont le même objet.x is not y
donne la valeur de vérité inverse.
Le is not
est spécifiquement prévu dans le Python grammaire comme amélioration de la lisibilité pour le langage:
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
Et c'est donc un élément unitaire de la grammaire.
Bien sûr, ce n’est pas pareil:
>>> import ast
>>> ast.dump(ast.parse('x is not None').body[0].value)
"Compare(left=Name(id='x', ctx=Load()), ops=[IsNot()], comparators=[Name(id='None', ctx=Load())])"
>>> ast.dump(ast.parse('not x is None').body[0].value)
"UnaryOp(op=Not(), operand=Compare(left=Name(id='x', ctx=Load()), ops=[Is()], comparators=[Name(id='None', ctx=Load())]))"
Mais le compilateur d’octets traduira le not ... is
en is not
:
>>> import dis
>>> dis.dis(lambda x, y: x is not y)
1 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
>>> dis.dis(lambda x, y: not x is y)
1 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
Donc, pour des raisons de lisibilité et d’utilisation du langage tel qu’il était destiné, veuillez utiliser is not
.
Ne pas l'utiliser n'est pas sage.
L'opérateur is not
est préférable à la négation du résultat de is
pour des raisons stylistiques. "if x is not None:
" se lit comme l’anglais, mais "if not x is None:
" nécessite de comprendre la priorité de l’opérateur et ne se lit pas comme l’anglais.
S'il y a une différence de performance, mon argent est sur is not
, mais ce n'est certainement pas ce qui motive la décision de préférer cette technique. Cela dépendrait évidemment de la mise en œuvre. Puisque is
n'est pas écrasable, il devrait être facile d'optimiser n'importe quelle distinction de toute façon.
Personnellement, j'utilise
if not (x is None):
ce qui est immédiatement compris sans ambiguïté par tous les programmeurs, même ceux qui ne sont pas experts en syntaxe Python.
if not x is None
est plus similaire aux autres langages de programmation, mais if x is not None
sonne nettement plus clair (et est plus correct grammaticalement en anglais).
Cela dit, il me semble que c'est plus une question de préférence.
Je préférerais la forme plus lisible x is not y
que je penserais comment écrire finalement la priorité de traitement de code des opérateurs afin de produire un code beaucoup plus lisible.