En muchos casos, Python se ve y se comporta como el inglés natural, pero este es un caso en el que falla esa abstracción. La gente puede usar pistas de contexto para determinar que "Jon" e "Inbar" son objetos unidos al verbo "igual", pero el intérprete de Python tiene una mentalidad más literal.
if name == "Kevin" or "Jon" or "Inbar":
es lógicamente equivalente a:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Lo que, para el usuario Bob, equivale a:
if (False) or ("Jon") or ("Inbar"):
El or
operador elige el primer argumento con un valor de verdad positivo :
if ("Jon"):
Y dado que "Jon" tiene un valor de verdad positivo, el if
bloque se ejecuta. Eso es lo que hace que se imprima "Acceso concedido" independientemente del nombre dado.
Todo este razonamiento también se aplica a la expresión if "Kevin" or "Jon" or "Inbar" == name
. el primer valor "Kevin"
,, es verdadero, por lo que el if
bloque se ejecuta.
Hay dos formas comunes de construir correctamente este condicional.
Utilice varios ==
operadores para comprobar explícitamente cada valor:
if name == "Kevin" or name == "Jon" or name == "Inbar":
Componga una secuencia de valores válidos y use el in
operador para probar la pertenencia:
if name in {"Kevin", "Jon", "Inbar"}:
En general, de los dos, debería preferirse el segundo, ya que es más fácil de leer y también más rápido:
>>> 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
Para aquellos que quieran una prueba de que de if a == b or c or d or e: ...
hecho se analiza así. El ast
módulo integrado proporciona una respuesta:
>>> 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=[])])"
>>>
Entonces, el test
de la if
declaración se ve así:
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())
]
)
Como se puede ver, es el operador booleano or
aplica a múltiples values
, a saber, a == b
y c
, d
, y e
.