これはとある日の出来事を基に記事を起こしています。
簡潔に
all関数と andの挙動は違う。
allは、すべての挙動を確認してbool値を返す。
andは、途中でfalseであれば、途中で評価を中断する。
導入
とある日のPR
if all([
hoge,
huga,
hoge < huga
]):
return 'hoge_gt_huga'
というコードをレビューした。
私 「hogeとhugaの値が入っているか確認してから、hoge < hugaの評価してるんやな!安全性高いコードやapproveや!」
その後、マージし、無事本番反映まで進みましたとさ。
翌日早朝(8時半)
sentry「エラーやで」
slack経由のsentryが急につぶやいた。
sentryの詳細をみると画面には昨日PRレビューした箇所と以下のエラー文を吐いていた
'<' not supported between instances of 'hoge' and 'NoneType'
私「っふぁ!なんでTypeError、しかも '<' 評価まで通過しとる、allってandと同じ意味じゃないんか」
そう私は以下の文と錯覚していたのです。
if hoge and huga and hoge < huga :
return 'hoge_gt_huga'
分析
通常andの場合は、第一にhoge、第二にhugaが評価した後に、第三のhoge < huga の評価が行われるため、TypeErrorにはならないのだが、allの場合は、すべての要件を評価した後に、bool値を返す仕組みのようだ。
このことから計算量についても全てを計算する場合(allの書き方)と、途中で計算が終わる場合(andの書き方)とで違いが出てくることもわかった。
むすび
ケースバイケースだが、nullableな変数を評価する場合は、allは避けるかある程度安全策をこうじる必要があるということが、今回のレビューで骨身にしみた。
すべての評価する値が完全にbool値になる時のみallは使いたいものですね。