In molti casi, Python sembra e si comporta come l'inglese naturale, ma questo è un caso in cui tale astrazione fallisce. Le persone possono usare indizi di contesto per determinare che "Jon" e "Inbar" sono oggetti uniti al verbo "uguale", ma l'interprete Python ha una mentalità più letterale.
if name == "Kevin" or "Jon" or "Inbar":
è logicamente equivalente a:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Che, per l'utente Bob, equivale a:
if (False) or ("Jon") or ("Inbar"):
L' or
operatore sceglie il primo argomento con un valore di verità positivo :
if ("Jon"):
E poiché "Jon" ha un valore di verità positivo, il file if
blocco viene eseguito. Questo è ciò che causa la stampa di "Accesso concesso" indipendentemente dal nome assegnato.
Tutto questo ragionamento vale anche per l'espressione if "Kevin" or "Jon" or "Inbar" == name
. il primo valore "Kevin"
,, è vero, quindi il if
blocco viene eseguito.
Esistono due modi comuni per costruire correttamente questo condizionale.
Utilizza più ==
operatori per verificare esplicitamente ogni valore:
if name == "Kevin" or name == "Jon" or name == "Inbar":
Componi una sequenza di valori validi e utilizza l' in
operatore per verificare l'appartenenza:
if name in {"Kevin", "Jon", "Inbar"}:
In generale dei due va preferito il secondo in quanto è più facile da leggere e anche più veloce:
>>> 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
Per coloro che desiderano una prova che if a == b or c or d or e: ...
è effettivamente analizzata in questo modo. Il ast
modulo integrato fornisce una risposta:
>>> 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=[])])"
>>>
Quindi il test
della if
dichiarazione assomiglia a questo:
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())
]
)
Come si può vedere, è l'operatore booleano or
applicato a molteplici values
, cioè, a == b
e c
, d
e e
.