W wielu przypadkach Python wygląda i zachowuje się jak naturalny angielski, ale jest to jeden przypadek, w którym ta abstrakcja zawodzi. Ludzie mogą używać wskazówek kontekstowych, aby określić, że „Jon” i „Inbar” są obiektami połączonymi z czasownikiem „równa się”, ale interpreter Pythona jest bardziej dosłowny.
if name == "Kevin" or "Jon" or "Inbar":
jest logicznie równoważne z:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Co dla użytkownika Bob jest równoważne z:
if (False) or ("Jon") or ("Inbar"):
orOperator wybiera pierwszy argument z pozytywnej wartości logicznej :
if ("Jon"):
A ponieważ „Jon” ma dodatnią wartość prawdy, ifblok jest wykonywany. To właśnie powoduje, że "Przyznany dostęp" jest drukowany niezależnie od podanej nazwy.
Całe to rozumowanie odnosi się również do wyrażenia if "Kevin" or "Jon" or "Inbar" == name. pierwsza wartość "Kevin"to prawda, więc ifblok jest wykonywany.
Istnieją dwa typowe sposoby prawidłowego skonstruowania tego warunku.
Użyj wielu ==operatorów, aby jawnie sprawdzić każdą wartość:
if name == "Kevin" or name == "Jon" or name == "Inbar":
Utwórz sekwencję prawidłowych wartości i użyj inoperatora, aby przetestować członkostwo:
if name in {"Kevin", "Jon", "Inbar"}:
Ogólnie rzecz biorąc, druga powinna być preferowana, ponieważ jest łatwiejsza do odczytania, a także szybsza:
>>> 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
Dla tych, którzy mogą chcieć dowodu, który if a == b or c or d or e: ...rzeczywiście jest analizowany w ten sposób. Wbudowany astmoduł dostarcza odpowiedzi:
>>> 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=[])])"
>>>
Więc testz ifwyglądem rachunku, takich jak ten:
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())
]
)
Jak widać, jest to operator logiczna orzastosowana do wielokrotnego values, a mianowicie, a == bi c, di e.