記号ではなく3つの単語
Python の論理演算子は英単語の and、or、not です。ほかの言語では &&、||、! と書きます。Python では && と || は SyntaxError になり、! は !=(「等しくない」)の一部としてしか現れません。
True と False だけなら、ルールは予想どおりです。
a | b | a and b | a or b | not a |
|---|---|---|---|---|
True | True | True | True | False |
True | False | False | True | False |
False | True | False | True | True |
False | False | False | False | True |
and は両辺が真である必要があります。or は少なくとも一方が真であれば十分です。not は値を1つだけ受け取り、それを反転します。
実際のコードでは、両辺はたいてい比較式で、その結果が if や while に渡されます。
出力:
eligible
standard ticket
ほとんどの条件はここまでの知識で書けます。このページの残りでは、True や False 以外の値に対して演算子が何をするのか、そして式のどちら側が実行されるかを決めるルールを説明します。
truthy な値と falsy な値
and、or、not は真偽値に限らず、どんな値でも受け取れます。値が真とみなされるかどうかは、その値の真理値(truthiness)で決まります。次の値は falsy です。
FalseとNone- あらゆる数値型のゼロ:
0、0.0 - 空のコンテナと空文字列:
""、[]、()、{}、set()、range(0)
それ以外はすべて truthy で、"0"、"False"、[0]、-1 も truthy です。Python が値をどう分類するかは bool() で確かめられます。
出力:
0 False
1 True
-1 True
'' False
'0' True
[] False
[0] True
None False
0.0 False
文字列 "0" は空でない文字列なので truthy です。入力から数値を読み込み、変換する前に判定してしまう人はここでつまずきます。bool と int の関係については 数値と真偽値のページ で解説しています。
and と or はオペランドを返す
ここが Python とほとんどの言語との違いです。and と or は新しい True や False を作りません。渡された2つの値のうち、どちらかを返します。
x or yは、xが truthy ならxを返し、そうでなければyを返します。x and yは、xが falsy ならxを返し、そうでなければyを返します。
両方のオペランドが真偽値なら、「オペランドを返す」ことと「真偽値を返す」ことは同じです。だからこそ、ほかの型を混ぜるまでこの違いに気づきにくいのです。
not だけは例外で、常に True か False を返します。
and/or の式から本物の真偽値が必要なとき(たとえば値を保存するときや、bool を返すと約束している関数から返すとき)は、bool() で囲みます。
短絡評価
Python は and と or を左から右へ評価し、答えが決まった時点で止めます。
andは最初の falsy な値で止まります。そのあとに何があっても、式全体が真になることはないからです。orは最初の truthy な値で止まります。そのあとに何があっても、式全体が偽になることはないからです。
スキップされた側はまったく実行されません。呼ばれたときに表示する関数を使うと、その様子が見えます。
出力:
and:
checking A
False
or:
checking A
True
どちらの場合も B は一度も確認されません。短絡評価のおかげで、ガード条件を安全に書けます。次の各条件の後半は単独ではエラーになりますが、前半が問題のあるケースを除外したあとでしか実行されません。
低コストな判定や保護のための判定を先に置きましょう。順序を逆にして user.startswith("admin") and user is not None と書くと、user が None のときに AttributeError が発生します。
or と and を使ったパターン
or は最初の truthy なオペランドを返すので、1行でデフォルト値を設定できます。
出力:
Hello, Ada!
Hello, guest!
Hello, guest!
注意点は、or が None だけでなく、あらゆる falsy な値を置き換えることです。0、""、[] が正当な入力なら、or はそれを捨ててしまいます。
ゼロや空が有効な値のときは x if x is not None else default を使いましょう。この条件式については if/else のページ で解説しています。
and にも対になるパターンがあります。「最初の値が設定されているときだけ、この値を使う」というものです。あまり一般的ではなく、if で書いたほうが明快なことも多いので、使うのは控えめにしましょう。
優先順位:not、次に and、最後に or
3つが混ざった式では、Python はまず not、次に and、最後に or を適用します。==、<、in などの比較は、そのどれよりも先に適用されます。
a or b and c と (a or b) and c は同じ値から違う答えを出します。ですから、たまたまデフォルトの順序で正しい場合でも、演算子が混ざった条件にはカッコを付けておきましょう。コストはかからず、次に読む人が迷わずに済みます。
and/or と &/| の違い
& と | は and や or と見た目が似ていて、同じ答えを返すこともありますが、別の演算子です。
and/orは truthy かどうかを調べ、短絡評価をし、オペランドのどちらかを返します。&/|はビット演算子です。整数に対しては2つの数のビットを組み合わせます。集合に対しては共通部分と和集合を意味します。TrueとFalseに対しては真偽値を返します。短絡評価は決して行わず、常に両辺が評価されます。
ビット演算子は比較演算子よりも優先順位が高いので、& で書いた条件はまったく別の意味になってしまいます。
1 & y は 1 & 5 で、これは 1 です。そのため真ん中の行は連鎖比較 5 > 1 > 1 になり、1 > 1 は偽です。ふつうの Python コードでは、条件には and、or、not を使いましょう。
条件に &、|、~ を使うのが正しいのは NumPy と pandas だけです。配列は多くの値を持つので、1つの真理値を持ちません。そのため and を使うと ValueError: The truth value of an array ... is ambiguous が発生します。これらのライブラリは & と | をオーバーロードして要素ごとに動作させています。pandas のフィルタが df[(df.age > 18) & (df.country == "CA")] のように書かれ、比較の1つ1つがカッコで囲まれているのは、上で説明した優先順位のためです。
any() と all():リスト全体に対する and と or
一連の条件をまとめて組み合わせるには、組み込み関数の all()(全要素に対する and)と any()(全要素に対する or)を使います。どちらも同じように短絡評価をします。
and や or と違い、any() と all() は常に真偽値を返します。
よくある間違い
1つの変数を or で複数の値と比較する。 次の最初の条件は常に真になります。
Python は最初の条件を (color == "red") or "blue" と解釈します。比較は False なので、or は "blue" を返します。これは空でない文字列なので truthy です。両側で比較を繰り返すか、もっとよいのは in でメンバーシップを判定することです。
&& や || を書く。 どちらも SyntaxError になります。and と or を使いましょう。
and/or から真偽値が返ると思い込む。 x = a or b は a か b そのものを格納します。それが望みどおりのことも多いのですが、関数が True か False を返すべきなら bool() で変換しましょう。
演算子が混ざった条件で優先順位に頼る。 a or b and c は正しく、意味もはっきり決まっていますが、誰もルールを思い出さなくて済むようにカッコを付けましょう。
よくある質問
Pythonの and 演算子は何をしますか?
a and b は両辺が真のときだけ真になります。Python はまず a を評価し、a が falsy なら b を見ずに a を返し、そうでなければ b を返します。ふつうの真偽値で使えば結果はおなじみのとおりで、True and False は False です。
0 or 5 が True ではなく 5 を返すのはなぜですか?
0 or 5 が True ではなく 5 を返すのはなぜですか?or と and は新しい真偽値を作るのではなく、オペランドのどちらかを返します。x or y は x が truthy なら x を、そうでなければ y を返します。0 は falsy なので、0 or 5 は 5 を返します。本物の True か False が必要なら、式を bool() で囲みます。
Pythonの and と & の違いは?
and と & の違いは?and は論理演算子で、truthy かどうかを調べ、短絡評価をします。& はビット演算子で、整数ならビット同士を組み合わせ(6 & 3 は 2)、集合なら共通部分をとり、常に両辺を評価します。if の条件には and を使いましょう。例外は NumPy と pandas で、そこでは & が要素ごとの and になります。
Pythonでは and と or のどちらが先に評価されますか?
結合が最も強いのは not、次が and、最後が or です。したがって a or b and c は a or (b and c)、not a or b は (not a) or b という意味になります。== や < などの比較演算子は、この3つのどれよりも強く結合します。
Pythonで && や || は使えますか?
使えません。Python では && と || は SyntaxError になります。論理演算子は単語の and、or、not です。& や | を1つだけ書くのは有効ですが、意味が違います(ビット単位の and/or)。