AND・OR・NOTと論理式
条件を組み合わせたときの真偽と、同じ意味になる論理式を学びます。
説明
条件式は、成り立つときに真、成り立たないときに偽になります。Pythonでは真をTrue、偽をFalseで表します。複数の条件を組み合わせるAND、OR、NOTは、プログラムの分岐や検索条件などに使われます。
このモジュールでは、二つの条件の全4通りを一度に表示し、演算ごとの結果を確認します。続いて、片方だけが真のXORと、NOTの付け方を変えて同じ意味の式を作るド・モルガンの法則を扱います。最後に、必要のない条件式は実行しない短絡評価の動作を確かめます。
1二つの条件の全組合せ
一つの条件にはFalseとTrueの2通りがあります。条件が二つなら2×2=4通りです。
from itertools import product全組合せを作る機能; pairs = list(product((False, True), repeat=2))真偽を二つ並べた全4組; pairs入力の組合せを表示False/False、False/True、True/False、True/Trueの4組です。以後、この順番で各論理式の結果を並べます。
2ANDは両方が真のときだけ真
ANDは、二つの条件がともに成り立つことを要求します。たとえば「会員である」と「予約済みである」の両方が必要な場合です。
[(a, b, a and b条件A・条件B・ANDの結果) for a, b in pairs全4組について計算]最後のTrue/Trueの組だけがTrueです。片方でもFalseなら、ANDの結果はFalseになります。
3ORは少なくとも片方が真なら真
ORは、どちらか一つでも条件が成り立てば真です。両方が成り立つ場合も含みます。
[(a, b, a or b条件A・条件B・ORの結果) for a, b in pairs全4組について計算]False/FalseだけがFalseで、残りはTrueです。日常語の「どちらか」と違って、論理のORは両方が真のケースを除外しません。
4XORは片方だけが真のとき真
両方が真のケースを除きたい場合は、排他的論理和XORを使います。真偽値同士なら、二つが等しくないかを調べる方法でも同じ結果になります。
[(a, b, a ^ b, a != b入力・XOR・不一致判定) for a, b in pairs全4組について計算]False/TrueとTrue/FalseだけがTrueです。^によるXORと!=による不一致の判定が、全4組で一致しています。
5NOTは真偽を反転する
NOTは一つの条件に適用します。条件が成り立たないことを表すために使います。
[(a, not a, not not a元の値・1回反転・2回反転) for a in (False, True)両方の入力を確認]FalseはTrueへ、TrueはFalseへ変わります。NOTを2回適用すると元の真偽に戻ります。
6AND全体を否定する式
「AとBが両方成り立つわけではない」は、「Aが成り立たない、またはBが成り立たない」と同じ意味です。二つの式を全入力で確認します。
[(a, b, not (a and b)AND全体を否定, (not a) or (not b)各条件を否定してORで結ぶ) for a, b in pairs全4組を比較]各行の最後の二つが一致します。AND全体を否定するときは、個々の条件を否定し、結び方をORへ変えます。これがド・モルガンの法則の一つです。
7OR全体を否定する式
「AもBも成り立たない」は、「AまたはBが成り立つ」の否定です。ORを使った式でも同じ対応を確認します。
[(a, b, not (a or b)OR全体を否定, (not a) and (not b)各条件を否定してANDで結ぶ) for a, b in pairs全4組を比較]今回も各行の二つの結果が一致します。OR全体を否定すると、個々の条件を否定したANDになります。条件を反転するときに、ANDとORの変更を忘れると別の意味になります。
8括弧の位置で意味が変わる
not (A and B)の括弧を外してnot A and Bとすると、NOTはAだけに掛かります。結果が違う入力を抽出します。
[(a, b) for a, b in pairs全入力を対象にする if (not (a and b)) != ((not a) and b)結果が異なる組だけを抽出]False/FalseとTrue/Falseで結果が変わります。否定する範囲を式の括弧で明示すると、この取り違えを防げます。
9ANDで後半を実行しない場合
左の条件がFalseなら、ANDの結果は右を調べる前にFalseと決まります。右の処理が実行されたらリストに記録する例で確認します。
calls = []実行記録を空にする; False and calls.append('right')右の処理が実行されるか調べる; calls実行記録を表示Falseの後に空のリストが表示されます。右側のappendが実行されていないため、記録は増えていません。これを短絡評価と呼びます。
10右側を評価する条件と、式の戻り値
左をTrueへ変えると、ANDは右の値を調べる必要があります。
True and calls.append('right')右の処理を実行; calls追加された記録を表示リストにrightが追加されました。appendの戻り値はNoneなので、この式自体の値は対話表示されません。Pythonのand/orは、必ずTrue/Falseを作る演算ではなく、評価したオペランドの値を返します。最初の真理値表では、入力を真偽値に限定していました。
まとめ
ANDは両方、ORは少なくとも片方、XORは片方だけが真のとき真です。NOTは真偽を反転します。
式全体の否定では、否定の範囲とAND/ORの変更に注意します。プログラムでは論理上の結果だけでなく、右側の処理が実行されるかも関係します。
操作履歴と解説を振り返れます。
Python 3
from itertools import product; pairs = list(product((False, True), repeat=2)); pairs[(False, False), (False, True), (True, False), (True, True)]
[(a, b, a and b) for a, b in pairs][(False, False, False), (False, True, False), (True, False, False), (True, True, True)]
[(a, b, a or b) for a, b in pairs][(False, False, False), (False, True, True), (True, False, True), (True, True, True)]
[(a, b, a ^ b, a != b) for a, b in pairs][(False, False, False, False), (False, True, True, True), (True, False, True, True), (True, True, False, False)]
[(a, not a, not not a) for a in (False, True)][(False, True, False), (True, False, True)]
[(a, b, not (a and b), (not a) or (not b)) for a, b in pairs][(False, False, True, True), (False, True, True, True), (True, False, True, True), (True, True, False, False)]
[(a, b, not (a or b), (not a) and (not b)) for a, b in pairs][(False, False, True, True), (False, True, False, False), (True, False, False, False), (True, True, False, False)]
[(a, b) for a, b in pairs if (not (a and b)) != ((not a) and b)][(False, False), (True, False)]
calls = []; False and calls.append('right'); callsFalse []
True and calls.append('right'); calls['right']
演習完了