値の比較・オブジェクトの同一性・短絡評価
リストの共有とコピーを比較し、関数の呼出し記録で評価順を確認します。最後に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
a = [1, 2]; b = [1, 2]; alias = a; print(a == b, a is b, a is alias)True False True
a.append(3); print(a, b, alias)[1, 2, 3] [1, 2] [1, 2, 3]
def probe(label, value):
print(label)
return valueprint(0 < probe("middle", 5) < 10); print(0 < probe("first", 5) and probe("second", 5) < 10)middle True first second True
print(probe("left", 0) and probe("right", 9)); print(probe("left", 1) and probe("right", 9))left 0 left right 9
denominator = 0; print(denominator != 0 and 12 / denominator > 2); denominator = 3; print(denominator != 0 and 12 / denominator > 2)False True
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
演習完了