web-dev-qa-db-fra.com

Si boucle: "x pas dans" vs "pas x dans"

J'ai remarqué que les deux fonctionnent de la même manière:

if x not in list et if not x in list.

Y a-t-il une sorte de différence entre les deux dans certains cas? Y a-t-il une raison d'avoir les deux, ou est-ce simplement parce qu'il est plus naturel pour certaines personnes d'écrire l'une ou l'autre?

Lequel suis-je le plus susceptible de voir dans le code des autres?

54
avacariu

Les deux formulaires font un bytecode identique, comme vous pouvez clairement le vérifier:

>>> import dis
>>> dis.dis(compile('if x not in d: pass', '', 'exec'))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_NAME                1 (d)
              6 COMPARE_OP               7 (not in)
              9 JUMP_IF_FALSE            4 (to 16)
             12 POP_TOP             
             13 JUMP_FORWARD             1 (to 17)
        >>   16 POP_TOP             
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE        
>>> dis.dis(compile('if not x in d: pass', '', 'exec'))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_NAME                1 (d)
              6 COMPARE_OP               7 (not in)
              9 JUMP_IF_FALSE            4 (to 16)
             12 POP_TOP             
             13 JUMP_FORWARD             1 (to 17)
        >>   16 POP_TOP             
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE        

donc évidemment ils sont sémantiquement identiques.

Pour une question de style, PEP 8 ne mentionne pas le problème.

Personnellement, je préfère fortement le formulaire if x not in y - qui indique immédiatement que not in Est un opérateur unique, et "se lit comme l'anglais". if not x in y Peut induire certains lecteurs en erreur en leur faisant croire que cela signifie if (not x) in y, se lit un peu moins comme l'anglais et n'a absolument aucun avantage compensatoire.

67
Alex Martelli
>>> dis.dis(lambda: a not in b)
1           0 LOAD_GLOBAL              0 (a)
          3 LOAD_GLOBAL              1 (b)
          6 COMPARE_OP               7 (not in)
          9 RETURN_VALUE      

>>> dis.dis(lambda: not a in b)
1           0 LOAD_GLOBAL              0 (a)
          3 LOAD_GLOBAL              1 (b)
          6 COMPARE_OP               7 (not in)
          9 RETURN_VALUE  

quand vous ne "pas a en b" il devra être converti pour (pas en)

donc, la bonne façon est "un pas en b".

6
killown

not x in L n'est pas explicitement interdit car ce serait idiot. x not in L est explicitement autorisé (bien qu'il compile dans le même bytecode) car il est plus lisible.

x not in L c'est ce que tout le monde utilise.

4
habnabit

Lorsque vous écrivez a not in b il utilise le not in, tandis que not a in b utilise l'opérateur in puis annule le résultat. Mais le not in L'opérateur est défini pour renvoyer la même chose que not a in b donc ils font exactement la même chose. De la documentation :

Les opérateurs in et not in test pour l'appartenance à la collection. x in s a la valeur true si x est membre de la collection s, et false sinon. x not in s renvoie la négation de x in s.

De même, il y a a is not b contre not a is b.

La syntaxe supplémentaire a été ajoutée car elle facilite la lecture naturelle par un humain.

3
Mark Byers

C'est juste une préférence personnelle. Vous pouvez également comparer if x != 3 et if not x == 3. Il n'y a aucune différence entre les deux expressions que vous avez montrées.

1
Ned Batchelder