Dans de nombreux cas, Python ressemble et se comporte comme un anglais naturel, mais c'est un cas où cette abstraction échoue. Les gens peuvent utiliser des indices de contexte pour déterminer que «Jon» et «Inbar» sont des objets joints au verbe «égal», mais l'interpréteur Python est plus littéral.
if name == "Kevin" or "Jon" or "Inbar":
équivaut logiquement à:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Ce qui, pour l'utilisateur Bob, équivaut à:
if (False) or ("Jon") or ("Inbar"):
L' or
opérateur choisit le premier argument avec une valeur de vérité positive :
if ("Jon"):
Et comme "Jon" a une valeur de vérité positive, le if
bloc s'exécute. C'est ce qui provoque l'impression de "Accès accordé" quel que soit le nom donné.
Tout ce raisonnement s'applique également à l'expression if "Kevin" or "Jon" or "Inbar" == name
. la première valeur "Kevin"
,, est vraie, donc le if
bloc s'exécute.
Il existe deux façons courantes de construire correctement ce conditionnel.
Utilisez plusieurs ==
opérateurs pour vérifier explicitement chaque valeur:
if name == "Kevin" or name == "Jon" or name == "Inbar":
Composez une séquence de valeurs valides et utilisez l' in
opérateur pour tester l'appartenance:
if name in {"Kevin", "Jon", "Inbar"}:
En général, le second devrait être préféré car il est plus facile à lire et aussi plus rapide:
>>> import timeit
>>> timeit.timeit('name == "Kevin" or name == "Jon" or name == "Inbar"', setup="name='Inbar'")
0.4247764749999945
>>> timeit.timeit('name in {"Kevin", "Jon", "Inbar"}', setup="name='Inbar'")
0.18493307199999265
Pour ceux qui veulent une preuve qui if a == b or c or d or e: ...
est en effet analysée comme ça. Le ast
module intégré fournit une réponse:
>>> import ast
>>> ast.parse("if a == b or c or d or e: ...")
<_ast.Module object at 0x1031ae6a0>
>>> ast.dump(_)
"Module(body=[If(test=BoolOp(op=Or(), values=[Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), Name(id='c', ctx=Load()), Name(id='d', ctx=Load()), Name(id='e', ctx=Load())]), body=[Expr(value=Ellipsis())], orelse=[])])"
>>>
Ainsi , le test
des if
états se présente comme suit:
BoolOp(
op=Or(),
values=[
Compare(
left=Name(id='a', ctx=Load()),
ops=[Eq()],
comparators=[Name(id='b', ctx=Load())]
),
Name(id='c', ctx=Load()),
Name(id='d', ctx=Load()),
Name(id='e', ctx=Load())
]
)
Comme on peut le voir, il est l'opérateur booléen or
appliqué à plusieurs values
, à savoir, a == b
et c
, d
et e
.