多くの場合、Pythonは自然な英語のように見え、動作しますが、これはその抽象化が失敗する1つのケースです。人々は文脈の手がかりを使用して、「Jon」と「Inbar」が動詞「equals」に結合されたオブジェクトであると判断できますが、Pythonインタープリターは文字通りの考え方です。
if name == "Kevin" or "Jon" or "Inbar":
論理的には次と同等です。
if (name == "Kevin") or ("Jon") or ("Inbar"):
ユーザーBobにとって、これは次と同等です。
if (False) or ("Jon") or ("Inbar"):
or
オペレータは、正と最初の引数を選択した真理値を:
if ("Jon"):
また、「Jon」には正の真理値があるため、if
ブロックが実行されます。これが、指定された名前に関係なく「アクセス許可」が印刷される原因です。
この推論はすべて式にも当てはまりますif "Kevin" or "Jon" or "Inbar" == name
。最初の値"Kevin"
はtrueなので、if
ブロックが実行されます。
この条件を適切に構築するには、2つの一般的な方法があります。
複数の==
演算子を使用して、各値を明示的にチェックします。
if name == "Kevin" or name == "Jon" or name == "Inbar":
有効な値のシーケンスを作成し、in
演算子を使用してメンバーシップをテストします。
if name in {"Kevin", "Jon", "Inbar"}:
読みやすく、高速であるため、一般的には2つ目が推奨されます。
>>> 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())
]
)
1が見ることができるように、それはブール演算子だor
複数に適用されるvalues
、すなわち、a == b
とc
、d
とe
。