型 bool

続いてbool型です。実際には整数型の1つです。型としてのboolのお話と、実際に使用するときに度々遭遇する変換、特に文字列からの変換についてもフォーカスを当てて説明します。

ここで学習すること

  • 型としてのbool
  • boolへの変換

サンプルコード

sample01.py

#!/usr/bin/env python3.8

def TrueOrFalse(value):
    if value: 
        print("True")
    else:
        print("False")

TrueOrFalse(0)
TrueOrFalse(0.0)
TrueOrFalse("")
TrueOrFalse([])
TrueOrFalse(())
TrueOrFalse({})

説明

型としてのbool

boolは2つの値をとります。真偽値の False と True を表します。殆どの場合0と1として振る舞いますが、例外として文字列に変換されたときはそれぞれ "False"および "True" という文字列が返されます。

その他、数値の 0 や 0.0、空文字(“”)、空リスト([])、空タプル(())、空辞書({})などを偽とみなしFalseとして扱われます。

では実際に動かして確かめてみます。

実行

$ python sample.py 
False
False
False
False
False
False
$ 

想定通り(説明の通り)ですね。

覚え方はFalseは0ということです。(実際の所Falseというのは0なんですが) つまり””とか{}とか[]とかゼロっぽいものはFalseになりますが、それ以外は”False”も含めてTrueになります。

boolへの変換

何らかの型の値をbool()で変換するという必要性が発生するかも知れませんが、前述の型としてのboolにおいて確かめてしまっている通り、直接if文の比較式としても用いることが出来ます。つまり、本当にboolに変換したいのかというと、直接if文に使ってしまえば良くてので正直なところそれほど多くはなさそうです。

むしろbool()の動作として誤解が生じそうなのは、bool(“False”)がTrueを返すので変換するときには注意が必要ですし、if文に直接使ってもそれは変わらないという事実です。

またbool(“False”)がTrueを返すという動作は、例えばデバッグを有効無効の切り替えを環境変数でDEBUG等の値をPythonプログラムで読み取る(os.getenv(“DEBUG”)ことで行う場合などには大きな過ちに繋がります。

本番環境でDEBUG=”False”はやってはいけない間違いで、正解はDEBUG=””だなんて、コンピュータがご主人様でエンジニアが使用人感が半端ないです。

もう一つのBoolへの変換strtobool()

boolへの変換で一番起こりそうな問題としてbool(“False”)を取り上げましたが、それを回避する、というかもっと直感的な動きをするstrtobool()をご紹介します。

その名の通りstr型からの変換に限ってしまいますが、こちらは思った通りの動作します。

from distutils.util import strtobool


def TrueOrFalse(value):
    if value:
        print("True")
    else:
        print("False")


print("Trueと期待されるもの")
TrueOrFalse(strtobool("TRUE"))
TrueOrFalse(strtobool("True"))
TrueOrFalse(strtobool("true"))
TrueOrFalse(strtobool("YES"))
TrueOrFalse(strtobool("Yes"))
TrueOrFalse(strtobool("yes"))
TrueOrFalse(strtobool("Y"))
TrueOrFalse(strtobool("y"))
TrueOrFalse(strtobool("T"))
TrueOrFalse(strtobool("t"))
TrueOrFalse(strtobool("1"))

print("Falseと期待されるもの")
TrueOrFalse(strtobool("FALSE"))
TrueOrFalse(strtobool("False"))
TrueOrFalse(strtobool("false"))
TrueOrFalse(strtobool("NO"))
TrueOrFalse(strtobool("No"))
TrueOrFalse(strtobool("no"))
TrueOrFalse(strtobool("N"))
TrueOrFalse(strtobool("n"))
TrueOrFalse(strtobool("F"))
TrueOrFalse(strtobool("f"))
TrueOrFalse(strtobool("0"))

実際に動作を確認してみます。

(LearningDjango) MacBookPro:tmp $ python test.py
Trueと期待されるもの
True
True
True
True
True
True
True
True
True
True
True
Falseと期待されるもの
False
False
False
False
False
False
False
False
False
False
False
(LearningDjango) MacBookPro:tmp $

期待通りに動作しています。1つだけ注意点は、strtobool("OK")などとやるとValueErrorが発生します。でもこれは、知らないうちにTrueかFalseになるより100倍マシですかね。

最後にもう少しだけ厳密な話をすると、strtobool()が実際に返すのは1か0でありTrue/Falseではありません。

つまりそれはTrue/Falseとして扱ってしまうと今度は別の問題を生じさせてしまいます。

なんだか、どこに行っても注意事項ばかりですっきりしませんね。

まとめ

当記事の冒頭に、以下のように記載しました。

boolは2つの値をとります。真偽値の False と True を表します。殆どの場合0と1として振る舞いますが、例外として文字列に変換されたときはそれぞれ "False"および "True" という文字列が返されます。

実際、0はFalseとして、1はTrueとして扱われます。

そもそもなのですが、Pythonにおけるboolは「2つある整数」の1つです。もう一つは日常「整数」として考えている整数です。整数の中に整数(int)とブール値(bool)があって、前者の0は文字列に変換すると”0″、後者の0は文字列に変換すると”False”になる、そうイメージすると上記の説明はしっくりくるのではないでしょうか。

boolはif文に必須の型で、「自分は間違っていない、Pythonが間違っている」系のドハマリする可能性をはらんでいるので、しっかり動きを抑えておきたいですね。