У багатьох випадках Python виглядає і поводиться як природний англійський, але це один випадок, коли ця абстракція не вдається. Люди можуть скористатися контекстними підказками, щоб визначити, що "Джон" та "Інбар" - це об'єкти, приєднані до дієслова "дорівнює", але інтерпретатор Python має більшу буквальність.
if name == "Kevin" or "Jon" or "Inbar":
логічно еквівалентно:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Що для користувача Боба еквівалентно:
if (False) or ("Jon") or ("Inbar"):
or
Оператор вибирає перший аргумент з позитивним значенням істинності :
if ("Jon"):
А оскільки "Джон" має позитивне значення істини, if
блок виконує. Саме це спричиняє друк "Доступ надано" незалежно від вказаної назви.
Все це міркування стосується і виразу if "Kevin" or "Jon" or "Inbar" == name
. перше значення "Kevin"
,, є істинним, тому if
блок виконує.
Існують два загальних способу правильної побудови цього умовного.
Використовуйте кілька ==
операторів, щоб чітко перевірити кожне значення:
if name == "Kevin" or name == "Jon" or name == "Inbar":
Складіть послідовність дійсних значень та скористайтеся in
оператором для перевірки на приналежність:
if name in {"Kevin", "Jon", "Inbar"}:
Загалом, слід віддати перевагу другому, оскільки його легше читати, а також швидше:
>>> 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
Для тих, хто може захотіти доказів, які if a == b or c or d or e: ...
насправді розбираються таким чином. Вбудований ast
модуль забезпечує відповідь:
>>> 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=[])])"
>>>
Таким чином, test
з if
заяви виглядає наступним чином :
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())
]
)
Як можна бачити, це логічний оператор or
застосовується до кількох values
, а саме, a == b
і c
, d
і e
.