一覧PG-03-2 · 演算子と評価順

値の比較・オブジェクトの同一性・短絡評価

リストの共有とコピーを比較し、関数の呼出し記録で評価順を確認します。最後に0を含む代替値の選び方を試し、実行された処理と返った値を対応付けます。

説明

値が等しいことと、同じオブジェクトを参照していることは別です。また、andとorは常に両側を実行する演算ではなく、左側の値で右側の評価を省略します。

リストの共有とコピーを比較し、関数の呼出し記録で評価順を確認します。最後に0を含む代替値の選び方を試し、実行された処理と返った値を対応付けます。

1内容と同一性

同じ内容の別リストbと、aを共有するaliasを作ります。

a = [1, 2]; b = [1, 2]; alias = a別リストと共有する別名; print(a == b, a is b, a is alias)値の一致と同一性

aとbは内容が等しいので==はTrueですが、別のリストなのでisはFalseです。aliasは同じリストを参照しているためisがTrueになります。

2共有しているリストを更新

aへ一つ追加し、三つの名前から内容を確認します。

a.append(3)aのリストを更新; print(a, b, alias)共有範囲を確認

aliasからも3が見えますが、bは変わりません。値の比較だけでは、後の変更を共有するか判断できません。isは整数の値を比較する代用品としては使わず、共有やNoneなどを調べる目的で使います。

3評価された関数を記録する

呼ばれたらラベルを表示し、受け取った値をそのまま返すprobeを定義します。

def probe(label, value):観測用の関数 print(label)評価された位置を表示 return value条件に使う値を返す

これから出るラベルは実際に関数を呼んだ順序です。返り値と表示の両方を観察すると、どこまで評価されたか分かります。

4連鎖比較の中央は一度だけ

同じ値5を範囲判定します。連鎖比較と、呼出しを二度書いたandの式を続けて実行します。

print(0 < probe("middle", 5) < 10中央を一度評価); print(0 < probe("first", 5) and probe("second", 5) < 10呼出しを二度記述)

連鎖比較ではmiddleが一度、後半ではfirstとsecondが出ます。0 < x < 10は中央の式を一度だけ評価します。関数に副作用があれば、この回数の違いが動作へ影響します。

5andの右側を省略する

左側を偽にしてから、真に変更します。戻り値も表示します。

print(probe("left", 0) and probe("right", 9)偽なら右を省略); print(probe("left", 1) and probe("right", 9)真なら右も評価)

最初はleftだけで0が返り、次はleftとrightが出て9が返ります。andが返すのは最後に評価した側の値であり、必ずboolへ変換した値ではありません。

6ゼロ除算を避ける条件

分母が0のときは右側の割算まで進まないようにします。

denominator = 00の分母; print(denominator != 0 and 12 / denominator > 2先に安全条件を判定); denominator = 3割算できる分母; print(denominator != 0 and 12 / denominator > 2右の式まで評価)

0ではFalseで終わり、ゼロ除算は起きません。3では割算まで進んでTrueです。安全に評価できる条件を左に置くことに意味があります。

7orで代替値を選ぶと0も置き換わる

在庫0を正当な値として残したい場面で、orとNoneの明示判定を比較します。

stock = 0正当な在庫0; print(stock or 99, 99 if stock is None else stock偽判定と不在判定); stock = None未登録の値; print(stock or 99, 99 if stock is None else stock未登録時の代替値)

orは左が偽なら右の値へ進むため、0も99になります。Noneだけを不在とする条件なら0を保持できます。代替値を使う条件を、データの意味に合わせて決めます。

まとめ

==は内容、isは同一オブジェクトかを調べます。

短絡評価で右側が実行される条件と、演算が返す値を確認します。

操作履歴と解説を振り返れます。

Python 3

1
a = [1, 2]; b = [1, 2]; alias = a; print(a == b, a is b, a is alias)
True False True
2
a.append(3); print(a, b, alias)
[1, 2, 3] [1, 2] [1, 2, 3]
3
def probe(label, value): print(label) return value
4
print(0 < probe("middle", 5) < 10); print(0 < probe("first", 5) and probe("second", 5) < 10)
middle
True
first
second
True
5
print(probe("left", 0) and probe("right", 9)); print(probe("left", 1) and probe("right", 9))
left
0
left
right
9
6
denominator = 0; print(denominator != 0 and 12 / denominator > 2); denominator = 3; print(denominator != 0 and 12 / denominator > 2)
False
True
7
stock = 0; print(stock or 99, 99 if stock is None else stock); stock = None; print(stock or 99, 99 if stock is None else stock)
99 0
99 99

演習完了