"X pas en y" ou "pas x en y"

97

Lors du test d'adhésion, nous pouvons utiliser:

x not in y

Ou bien:

not x in y

Il peut y avoir de nombreux contextes possibles pour cette expression en fonction de xet y. Cela peut être pour une vérification de sous-chaîne, une appartenance à une liste, une existence de clé dict, par exemple.

  • Les deux formes sont-elles toujours équivalentes?
  • Existe-t-il une syntaxe préférée?
wim
la source

Réponses:

112

Ils donnent toujours le même résultat.

En fait, not 'ham' in 'spam and eggs'semble être une casse spéciale pour effectuer une seule opération "pas en", plutôt qu'une opération "en", puis annuler le résultat:

>>> import dis

>>> def notin():
    'ham' not in 'spam and eggs'
>>> dis.dis(notin)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not_in():
    not 'ham' in 'spam and eggs'
>>> dis.dis(not_in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not__in():
    not ('ham' in 'spam and eggs')
>>> dis.dis(not__in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

>>> def noteq():
    not 'ham' == 'spam and eggs'
>>> dis.dis(noteq)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT           
             10 POP_TOP             
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE      

J'avais pensé au début qu'ils donnaient toujours le même résultat, mais que notseul était simplement un opérateur de négation logique à faible priorité, qui pouvait être appliqué a in baussi facilement que n'importe quelle autre expression booléenne, alors qu'il not ins'agissait d'un opérateur séparé pour plus de commodité et de clarté .

Le démontage ci-dessus était révélateur! Il semble que bien qu'il s'agisse notévidemment d'un opérateur de négation logique, le formulaire not a in best spécialement casse afin qu'il n'utilise pas réellement l'opérateur général. Cela fait not a in blittéralement la même expression que a not in b, plutôt que simplement une expression qui donne la même valeur.

Ben
la source
4
Gardez à l'esprit qu'il ne s'agit que d'un détail de mise en œuvre. Je ne trouve même pas de mention not x in xsdans la documentation.
phant0m
1
@ phant0m Absolument; la façon dont vous êtes censé penser not x in xsest not (x in xs). Mais le fait qu'il soit implémenté en l'analysant exactement dans le même bytecode x not in xsmontre très clairement qu'ils doivent être toujours identiques, par opposition à des choses comme not x == yvs x != yqui devraient donner le même résultat, mais pas obligées (selon les implémentations de __eq__et __ne__impliqué).
Ben
11
Vous avez rencontré une optimisation du judas CPython ; une optimisation au moment de la compilation que d'autres implémentations Python telles que Jython et IronPython sont libres d'ignorer ou de copier (cela ne fait pas partie de la spécification du langage).
Martijn Pieters
15

  1. Non, il n'y a pas de différence.

    L'opérateur not inest défini pour avoir la valeur vraie inverse de in.

    - Documentation Python

  2. Je suppose que not inc'est préféré parce que c'est plus évident et qu'ils ont ajouté un cas spécial pour cela.

icktoofay
la source
3

D'autres ont déjà indiqué très clairement que les deux déclarations sont, à un niveau assez bas, équivalentes.

Cependant, je ne pense pas que quiconque ait encore suffisamment insisté pour que, puisque cela vous laisse le choix, vous devriez

choisissez la forme qui rend votre code aussi lisible que possible.

Et pas nécessairement aussi lisible que possible pour quiconque , même si c'est bien sûr une bonne chose à viser. Non, assurez-vous que le code est aussi lisible que possible pour vous , car c'est vous qui êtes le plus susceptible de revenir sur ce code plus tard et d'essayer de le lire.

Tomas Aschan
la source
Si vous travaillez dans une grande équipe ou sur du code qui restera probablement intact pendant un certain temps, il est plus probable que quelqu'un d'autre doive le maintenir.
Tommy Herbert
2

En Python, il n'y a pas de différence. Et il n'y a aucune préférence.

Ignacio Vazquez-Abrams
la source
1

Syntaxiquement, ils sont la même déclaration. Je serais prompt à déclarer que cela 'ham' not in 'spam and eggs'transmet une intention plus claire, mais j'ai vu du code et des scénarios dans lesquels not 'ham' in 'spam and eggs'transmet une signification plus claire que l'autre.

Makoto
la source