0
0

More than 1 year has passed since last update.

Pythonの論理演算子andとorは必ずしもbool型を返さない

Posted at

研究やらで数年間Pythonを書いてきたのに知らなかった。
備忘録として残しておきます。初心者なので細かい点はご容赦ください。

普通、A and B、A or B(言語によってはA && B、A || Bなどの場合も)は、AとBの論理演算を行った結果を返します。
つまり、A、B、演算結果はすべて真偽値となり、Pythonではbool型となる……と、思っていました。

しかし、実際には以下のようなプログラムも実行できます。

x = 1 and 2
print(x)

y = "かぶと" or "くわがた" 
print(y)
実行結果
2
かぶと

ご覧の通り、数値や文字列に対してもand・or演算子が機能し、またbool型ではない結果が返ってきています。

これは、Pythonでは、A and B及びA or Bが次のような仕組みになっていることに由来します。

A and B
if not bool(A): # Aをbool型に変換した結果がFalseの場合
    return A # Aを返却(Aをbool型に変換した結果ではない!)
else: # Aをbool型に変換した結果がTrueの場合
    return B # Bを返却(これもBの変換結果ではない!)
A or B
if bool(A): # Aをbool型に変換した結果がTrueの場合
    return A # Aを返却(Aをbool型に変換した結果ではない!)
else: # Aをbool型に変換した結果がFalseの場合
    return B # Bを返却(これもBの変換結果ではない!)

bool()は引数をbool型に変換する関数です。
これによってA、Bをbool型に直してから評価し、返却する時には元の値をそのまま返す、という動きをします。
よってA、Bがbool型でなくても機能しますし、返却される値はbool型とは限らない、というわけでした。

bool()によってTrue、Falseと判断される値には、それぞれどんなものがあるのでしょうか。
公式リファレンスでは以下のもの、もしくは省略された場合にFalseとなり、

  • 偽であると定義されている定数: None, False
  • 数値型におけるゼロ: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • 空のシーケンスまたはコレクション: '', (), [], {}, set(), range(0)

これら以外の場合Trueを返す、とあります。
これらの仕様を利用して、例えば次のような利用法が期待できます。

# sが文字列の時、空文字列の場合のみ"foo"を格納する
s = s or "foo"

余談ですが、A and B、A or Bともに「Bが評価されない場合」があります。
A and Bではbool(A)Falseの場合、Bを評価せずAを返却します。
A or Bではbool(A)Trueの場合、Bを評価せずAを返却します。

詳しい説明はリンク先に譲りますが、これは短絡評価と呼ばれるもので、片方で論理式全体の結果がわかる場合にはそこで式の評価を打ち切るというものです。
Bが関数などの場合そもそも呼ばれないこともあるということで、注意が必要そうです。

まとめとして、ポイントを押さえておきます。

  • Pythonのand・or演算子はbool型以外にも使える
  • 同様に、and・or演算子の結果はbool型以外にもなりえる
  • 演算子の後ろにある項は呼ばれないこともある
0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0