Menu

Pythonの and・or・not|論理演算子、短絡評価、truthy と falsy

Pythonの and、or、not の仕組みを解説。真理値表、truthy と falsy、短絡評価、and/or がオペランドを返す理由、優先順位、and/or と & / | の違いまで。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

記号ではなく3つの単語

Python の論理演算子は英単語の and、or、not です。ほかの言語では &&、||、! と書きます。Python では && と || は SyntaxError になり、! は !=(「等しくない」)の一部としてしか現れません。

True と False だけなら、ルールは予想どおりです。

aba and ba or bnot a
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue

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 を返すのはなぜですか?

or と and は新しい真偽値を作るのではなく、オペランドのどちらかを返します。x or y は x が truthy なら x を、そうでなければ y を返します。0 は falsy なので、0 or 5 は 5 を返します。本物の True か False が必要なら、式を bool() で囲みます。

Pythonの 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)。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める