[解決済み] なぜ「a == x or y or z」は常に「真」と評価されるのですか?
疑問点
不正なユーザがアクセスできないようにするセキュリティシステムを書いています。
name = input("Hello. Please enter your name: ")
if name == "Kevin" or "Jon" or "Inbar":
print("Access granted.")
else:
print("Access denied.")
期待通りに正規のユーザーにアクセスを許可していますが、未認証のユーザーも入ってきてしまいます!
Hello. Please enter your name: Bob
Access granted.
なぜこのようなことが起こるのでしょうか?私は、以下の場合にのみアクセスを許可するように明白に述べています。
name
が Kevin、Jon、または Inbar に等しい場合にのみアクセスを許可すると明言しました。また、逆のロジックも試してみました。
if "Kevin" or "Jon" or "Inbar" == name
という逆のロジックも試してみましたが、結果は同じでした。
ノート : この質問は、この非常に一般的な問題の正規の重複対象として意図されています。別の普及した質問がある 1つの値に対して複数の変数が等しいかどうかをテストする方法は? という、同じ基本的な問題を持つ質問もありますが、比較対象が逆になっています。この問題は Python の初心者が遭遇するもので、反転した問題からの知識を自分の問題に適用するのが難しいかもしれないので、この質問をその重複として閉じるべきではありません。
どのように解決するのですか?
多くの場合、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
ブロックが実行されます。これが、与えられた名前に関係なく"Access granted"が出力される原因です。
この推論はすべて、式
if "Kevin" or "Jon" or "Inbar" == name
.最初の値である
"Kevin"
は真なので
if
ブロックが実行されます。
この条件を適切に構築する一般的な方法は2つあります。
-
複数の
==
演算子を使用して、各値に対して明示的にチェックします。if name == "Kevin" or name == "Jon" or name == "Inbar":
-
有効な値の集まり(例えばセット、リスト、タプル)を構成し、その中で
in
演算子を使用してメンバーシップをテストします。if name in {"Kevin", "Jon", "Inbar"}:
一般に、2つのうち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("a == b or c or d or e", "<string>", "eval")
<ast.Expression object at 0x7f929c898220>
>>> print(ast.dump(_, indent=4))
Expression(
body=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
を 4 つの部分式に適用したものです。
a == b
と単純な式
c
,
d
そして
e
.
関連
-
[解決済み】cアンダースコア式`c_`は、具体的に何をするのですか?
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] 割り当て後にリストが予期せず変更されました。その理由と防止策を教えてください。
-
[解決済み] パラメータに**(ダブルスター/アスタリスク)、*(スター/アスタリスク)がありますが、これはどういう意味ですか?
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] なぜlist.join(string)ではなくstring.join(list)なのでしょうか?
-
[解決済み】if __name__ == "__main__": は何をするのでしょうか?
-
[解決済み】Djangoでnull=Trueとblank=Trueの違いは何ですか?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python関数の高度な応用を解説
-
Python jiabaライブラリの使用方法について説明
-
Pythonの@decoratorsについてまとめてみました。
-
[解決済み】お使いのCPUは、このTensorFlowバイナリが使用するようにコンパイルされていない命令をサポートしています。AVX AVX2
-
[解決済み】Django: ImproperlyConfigured: SECRET_KEY 設定は空であってはならない
-
[解決済み】Flask ImportError: Flask という名前のモジュールがない
-
[解決済み】ValueError: pickleプロトコルがサポートされていません。3、python2 pickleはpython3 pickleでダンプしたファイルを読み込むことができない?
-
[解決済み】cアンダースコア式`c_`は、具体的に何をするのですか?
-
[解決済み】 'numpy.float64' オブジェクトは反復可能ではない
-
[解決済み】ValueError: xとyは同じサイズでなければならない