Python `si x n'est pas None` ou` sinon x n'est None`?


749

J'ai toujours pensé que la if not x is Noneversion était plus claire, mais le guide de style de Google et le PEP-8 utilisent tous les deux if x is not None. Y a-t-il une différence de performance mineure (je suppose que non), et y a-t-il un cas où l'un ne correspond vraiment pas (faisant de l'autre un gagnant clair pour ma convention)? *

* Je fais référence à n'importe quel singleton, plutôt que juste None.

... pour comparer des singletons comme None. L'utilisation est ou n'est pas.


8
is notest un opérateur à part entière. Comme !=. Si vous préférez not x is None, votre devrait aussi préférer not a == bplus a != b.
Tomasz Gandor

@TomaszGandor Je n'ai plus cette opinion sur not x is None(les réponses ici m'ont convaincu) - il convient cependant de noter que not a == bc'est le style préféré en Python par rapport à a != b.
orokusaki

4
@orokusaki est not a == bvraiment le style préféré? Je ne l'ai jamais vu faire de cette façon et partout où je regarde les gens utilisent tous !=.
Mike - SMT

2
@orokusaki Dans nombre de lisibilité Python donc il est un style préféré d'utiliser un opérateur au !=lieu de deux opérateurs not, ==.
Jeyekomon

Réponses:


995

Il n'y a aucune différence de performances, car ils se 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'essaye d'éviter not x is y. Bien que le compilateur le traite toujours comme not (x is y), un lecteur humain peut mal comprendre la construction comme (not x) is y. Si j'écris, x is not yil n'y a pas d'ambiguïté.


103
À moins que le même lecteur humain ne le pense x is (not y). Mais j'ai tendance à être d'accord avec vous pour votre autre raisonnement.
Etaoin

24
En outre «n'est pas » est moins ambiguë dans ce contexte , « si un est None et b est None: » vs « sinon est None et b est None: »
Gordon Wrigley

45
l'opérateur doit être "aint"
bean

217

Le guide de style de Google et de Python est la meilleure pratique:

if x is not None:
    # Do something about x

L'utilisation not xpeut 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 sur Trueou Falseen Python:


Modifier pour le commentaire ci-dessous:

Je viens de faire quelques tests supplémentaires. not x is Nonene nie pas d' xabord, puis par rapport à None. En fait, il semble que l' isopérateur 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, il not x is Noneest, à mon avis honnête, préférable d'éviter.


Plus modifier:

Je viens de faire plus de tests et je peux confirmer que le commentaire de bukzor est correct. (Au moins, je n'ai pas pu prouver le contraire.)

Cela signifie que if x is not Nonele résultat exact est if not x is None. Je me suis trompé. Merci bukzor.

Cependant, ma réponse est toujours valable: utilisez le conventionnelif x is not None .:]


131

Le code doit être écrit pour être compréhensible par le programmeur en premier, et le compilateur ou l'interpréteur en second. La construction "is not" ressemble plus à l'anglais que "not is".


33

Python if x is not Noneou if not x is None?

TLDR: le compilateur de bytecode les analyse tous les deux x is not None- donc pour des raisons de lisibilité, utilisez if x is not None.

Lisibilité

Nous utilisons Python parce que nous apprécions des choses comme la lisibilité humaine, l'utilisabilité et l'exactitude de divers paradigmes de programmation par rapport aux performances.

Python optimise la lisibilité, en particulier dans ce contexte.

Analyse et compilation du Bytecode

La not liaison est plus faible que is, il n'y a donc pas de différence logique ici. Consultez la documentation :

Les opérateurs iset le is nottest d'identité d'objet: x is yest vrai si et seulement si x et y sont le même objet. x is not ydonne la valeur de vérité inverse.

Le is notest spécifiquement prévu dans la grammaire Python comme une amélioration de la lisibilité du langage:

comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

Et c'est donc aussi 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 octet fait traduire not ... isà 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 de la langue comme prévu, veuillez utiliser is not.

Ne pas l'utiliser n'est pas sage.


"Le notlien est plus faible que is, donc il n'y a pas de différence logique ici" - sauf que Python n'a pas à imposer les identités logiques et algébriques (aucune raison intrinsèque pour (1 + 2)*3évaluer la même chose que 1*3 + 2*3). Ici, apparemment, Python triche et s'optimise UNARY_NOT.
Alexey

30

La réponse est plus simple que les gens ne le font.

Il n'y a aucun avantage technique de toute façon, et "x n'est pas y" est ce que tout le monde utilise , ce qui en fait le vainqueur incontestable. 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 en rien - le comprendra d'un coup d'œil, où la syntaxe légèrement moins courante prendra quelques cycles cérébraux supplémentaires à analyser.

Ne soyez pas différent juste pour être différent, au moins dans ce domaine.


11

L' is notopérateur est préférable à la négation du résultat ispour des raisons stylistiques. " if x is not None:" se lit comme l'anglais, mais " if not x is None:" nécessite la compréhension de 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 en jeu is not, mais ce n'est certainement pas la motivation pour la décision de préférer cette technique. Cela dépendrait évidemment de la mise en œuvre. Comme il isn'est pas possible de le remplacer, il devrait être facile d'optimiser n'importe quelle distinction de toute façon.


9

Personnellement, j'utilise

if not (x is None):

ce qui est compris immédiatement et sans ambiguïté par tous les programmeurs, même ceux qui ne sont pas experts en syntaxe Python.


5
Un argument juste avec lequel je suis d'accord, mais je crois que l'argument de suivre un style idiomatique est plus fort.
clacke

2

if not x is Noneest plus similaire aux autres langages de programmation, mais if x is not Nonesonne définitivement plus clair (et est plus grammaticalement correct en anglais) pour moi.

Cela dit, il semble que ce soit plus une préférence pour moi.


0

Je préférerais la forme plus lisible x is not y que je ne pense comment écrire éventuellement la priorité de gestion du code des opérateurs afin de produire un code beaucoup plus lisible.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.