Em muitos casos, Python se parece e se comporta como o inglês natural, mas este é um caso em que essa abstração falha. As pessoas podem usar pistas de contexto para determinar que "Jon" e "Inbar" são objetos unidos ao verbo "igual a", mas o interpretador Python é mais literal.
if name == "Kevin" or "Jon" or "Inbar":
é logicamente equivalente a:
if (name == "Kevin") or ("Jon") or ("Inbar"):
O que, para o usuário Bob, é equivalente a:
if (False) or ("Jon") or ("Inbar"):
O or
operador escolhe o primeiro argumento com um valor verdade positivo :
if ("Jon"):
E como "Jon" tem um valor verdadeiro positivo, o if
bloco é executado. Isso é o que faz com que "Acesso concedido" seja impresso independentemente do nome fornecido.
Todo esse raciocínio também se aplica à expressão if "Kevin" or "Jon" or "Inbar" == name
. o primeiro valor "Kevin"
,, é verdadeiro, então o if
bloco é executado.
Existem duas maneiras comuns de construir adequadamente esta condicional.
Use vários ==
operadores para verificar explicitamente cada valor:
if name == "Kevin" or name == "Jon" or name == "Inbar":
Componha uma sequência de valores válidos e use o in
operador para testar a associação:
if name in {"Kevin", "Jon", "Inbar"}:
Em geral dos dois, o segundo deve ser o preferido, pois é mais fácil de ler e também mais 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 aqueles que podem querer uma prova de que if a == b or c or d or e: ...
é realmente analisado assim. O ast
módulo integrado fornece uma resposta:
>>> 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=[])])"
>>>
Portanto, o test
da if
declaração é assim:
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 pode ver, é o operador booleano or
aplicada a múltiplos values
, ou seja, a == b
e c
, d
e e
.