Pythonの論理演算(ブール演算)のポイントは、①論理演算子(and, or, not)に優先順位があること。②数値や文字列の数値演算を行うこともでき、その場合演算結果がTrueやFalseにならないことです。ここでは、論理演算子の使い方の基本と、数値や文字列の論理演算について説明します。
1. 論理演算の基本
(1) 真偽値(論理値、bool値、boolean)
真偽値は、論理値、bool値(ブール値)、boolean(ブーリアン)ともいいます。
正しければ「真(True)」、誤りは「偽(False)」です。以下、具体例です。
(3 < 10) → 3 < 10は正しい → 真(True、トゥルー)
(4 < 3) → 4 < 3は誤り → 偽(False、フォールス)
(2) 論理演算子(ブール演算子、bool演算子)
論理演算子には「and」「or」「not」があります。数学の教科書などでもよく見かけるベン図を使うと、下図のようになります。andやorを用いて2つ以上の条件を1つにまとめたり、notを用いて条件の真偽を逆にしたりできます。
(a) 論理積 and
「A and B and C → A かつ B かつ C」
A, B, Cがすべて正しい(True)の場合はTrue。1つでも誤りがあるとFalse。
(b) 論理和 or
「A or B or C → A または B または C」
A, B, Cの内、1つでも正解(True)がある場合はTrue。全て誤りの場合はFalse。
(c) 否定 not
「not A → Trueではない→False、 Falseではない→True」
AがTrueなら、Falseに変換。AがFalseなら、Trueに変換。
(d) 具体例
ピンとこない方は、具体例を見た方が早いと思いますのでコード01を見てください。x = 3なので、x < 10 はTrue、4 < xはFalseです。5行目の論理積(and)は全てTrueでなければなりませんのでFalse、6行目の論理和は1つでもTrueであればTrueです。8~11行目はif文で用いた例です。 if文で「x < 10 and 4 < x」を用いることで、xが4より大きく10より小さい場合にTrueとなり8行目の命令文を実行します。
#コード01
x = 3
print('x < 10 →', x < 10) #True
print('4 < x →', 4 < x) #False
print('True and False →',x < 10 and 4 < x) #False
print('True or False →',x < 10 or 4 < x) #True
if x < 10 and 4 < x:
print('(x < 10) and (4 < x)はTrue')
else:
print('(x < 10) and (4 < x)はFalse')
#出力01
x < 10 → True
4 < x → False
True and False → False
True or False → True
(x < 10) and (4 < x)はFalse
2. 論理演算子(and, or, not)の優先順位
3 + 4 * 5の計算では3 + 4より4 * 5を優先して先に計算を行います。これと同じように論理演算子にも優先順位があります。優先順位が高い者から「not → and → or」です。なお、>, ==, >=等は「比較演算子」と呼ばれますが、比較演算子も含めた優先順位は、「比較演算子 → not → and → or」です。
論理演算子の優先順位についても、具体例(コード02)を見てみましょう。例1-1において、もし、orとandに優先順位がなければ、True or Trueが先に計算されるためFalseになるのですが、出力はTrueとなります。この結果からも、orよりもandの方が優先順位が高いことがわかります。以下、同様に例2-1と例2-2、例3-1と例3-2を比較し、優先順位が「or → and → or」の順番になっていることを確認してください。
この様に論理演算子には優先順位がありますので、特にandとorを併用する場合には()をつけて順序を明確にする方がエラーの少ないコードになるのではないかと思います。
#コード02
print('例1-1',True or True and False)
print('例1-2',(True or True) and False)
print('例2-1',True and not True)
print('例2-2',True and (not True))
print('例3-1',not False and False)
print('例3-2',not (False and False))
出力02
例1-1 True
例1-2 False
例2-1 False
例2-2 False
例3-1 False
例3-2 True
3. 数値や文字列の論理演算
数値123や文字列'abc'の論理演算は、Pythonの資格取得のためチュートリアルを読み込んでいる方や、興味のある方が読みましょう。興味のないかたは読み飛ばしてもよいのではないかと思います。
(1) 数値や文字列の真偽値
数値は0がFalse、0以外はTrueです。一方、文字列は空文字列(からもじれつ)はFalse、空文字列以外はTrueです。なお、空文字列は長さが0の文字列であり、「''」と記述します。
ところで、bool()関数は、数値や文字列を真偽値(ブール値)に変換できます。コード03では、数値や文字列の真偽値(ブール値)を、このbool()関数を用いて確かめます。コード03の2~5行目のbool()関数によって、数値や文字列が真偽値に変換されていることがわかります。
なお、if文の条件で数値や文字列を用いる場合は、7行目、13行目のように、「if 'abc':」といった記述でよく、「if bool('abc'):」のように、真偽値(ブール値)に変換する必要はありません。
#コード03
print(bool(123))
print(bool(0))
print(bool('abc'))
print(bool(''))
if 'abc':
print('abcはTrue')
else:
print('abcはFalse')
if '':
print("''はTrue")
else:
print("''はFalse")
#出力03
True
False
True
False
abcはTrue
''はFalse
(2) 数値や文字列の論理演算
数値や文字列の論理演算結果は、TrueやFalseで答えが返ってくるのではなく、数値や文字列で返されます。また、Pythonの論理演算では、必ずしも論理演算部分の最後まで検討されるのではなく、答えが確定すると残りの計算はせず、判断の決め手となった値を返します。
言葉ではわかりにくいので、コード04を見てください。3行目の(123 or 456 or 789)では、123がTrueなので残りの456, 789がどんな値であっても答えは確定します。したがって、456, 789についてはTrue, Falseの判定はせず、答えの決め手となった123を返します。
同様に(0 or 456 or 789)では、0→Falseだけでは答えが確定しませんが、次の456で答えが確定します。そこで、答えの決め手になった456を返します。その後の789は検討しません。
この様に、答えが確定した時点で評価をやめる演算子なので「短絡演算子」とも呼ばれます。
#コード04
print('数値の論理和')
print(123 or 456 or 789) #123
print(0 or 456 or 789) #456
print(0 or 0 or 789) #789
print(0 or 0 or 0) #0
print(123 or 0 or 0) #123
print('数値の論理積')
print(0 and 456 and 789) #0
print(123 and 0 and 789) #0
print(123 and 456 and 0) #0
print(0 and 0 and 0) #0
print(123 and 456 and 789) #789
#出力04
数値の論理和
123
456
789
0
123
数値の論理積
0
0
0
0
789
(3) if文への適用
「面倒だな~」と思ったかもしれませんが、実際に論理演算が用いられるのはif文などです。if文ではbool()関数を用いなくても、文字列や数値を自動で真偽値(bool値)に変換してくれます。したがって、論理演算の結果が「文字や数字」なのか「TrueやFalse」なのかを気にする必要はありません。コード05のように使用すればよいだけです。
#コード05
if (0 or 0 or 789):
print('(0 or 0 or 789)はTrue')
else:
print('(0 or 0 or 789)はFalse')
if (0 or 0 or 0):
print('(0 or 0 or 0)はTrue')
else:
print('(0 or 0 or 0)はFalse')
#出力05
(0 or 0 or 789)はTrue
(0 or 0 or 0)はFalse
念のため、コード04をbool()関数を用いて、真偽値(bool値)に変換してみます。それぞれ、答えが確定したときの決め手となった数値を返していますが、真偽値(bool値)に変換した結果と比較すると、問題なく論理演算が行われていることがわかります。
例えば(0 or 0 or 789)→789は、0がFalse, 789がTrueなので、読み替えれば(False or False or True) → Trueとなり、論理演算が正しく行われています。
#コード06
print('数値の論理和をbool値に変換')
print(bool(123 or 456 or 789)) #123 → True
print(bool(0 or 456 or 789)) #456 → True
print(bool(0 or 0 or 789)) #789 → True
print(bool(0 or 0 or 0)) #0 → False
print(bool(123 or 0 or 0)) #123 → True
print('数値の論理積をbool値に変換')
print(bool(0 and 456 and 789)) #0 → False
print(bool(123 and 0 and 789)) #0 → False
print(bool(123 and 456 and 0)) #0 → False
print(bool(0 and 0 and 0)) #0 → False
print(bool(123 and 456 and 789)) #789 → True
#出力06
数値の論理和をbool値に変換
True
True
True
False
True
数値の論理積をbool値に変換
False
False
False
False
True
4. 文字や数値と条件式の併用
>, ==, >=といった比較演算子を用いて値を比較した式を「条件式」といいます。そして、「条件式」と「文字や数値」は併用可能です。併用した具体例をコード06に示します。
print(0 and True)では、0はFalseなので、andより後ろのTrueを検証するまでもなく、Falseが確定します。従って、(0 and True)は決め手となった0を返します。
print(123 and True)では、123はTrueなので、andの後のTrueも検証する必要があります。and の後のTrueまで検証しなければ答えが出ないので、and の後のTrueが答えとして返されます。
print(0 and 3 < 5)やprint(123 and 3 < 5)は、3 < 5がTrueですので、2行目、3行目と同じ結果になります。
このように、数値や文字列や条件式を併用する場合、その結果は論理演算内容によって数値や文字列になったり、真偽値(ブール値)になったりします。
#コード07
print(0 and True)
print(123 and True)
print(0 and 3 < 5)
print(123 and 3 < 5)
#出力07
0
True
0
True
5. まとめ
論理演算の基本から数値や文字列の論理演算までを解説しました。ポイントは以下の通りです。
(1) 条件式論理演算子の優先順位は、「条件式 → not → and → or」
(2) 数値や文字列の論理演算結果はTrueやFalseではなく、数値や文字列を返す。
(3) if文の条件として数値や文字列を使う場合、数値や文字列をbool()関数などで真偽値に変換しなくても、数値や文字列のまま使用できる。
(4) 2つ以上の論理演算子(and, or)を用いて数値や文字列の論理演算を行う場合、結果が確定した時点で検証をやめ、結果の確定で決め手となった数値や文字列を返す。