連鎖比較と優先順位
このレッスンで作るもの —
0 <= price <= budgetのように比較を連ねる書き方と、演算子が計算される順番を整理します。
連鎖比較と優先順位
「金額が 0 円以上、かつ予算以下」を判定したいとします。前回までの道具で書くと下記のようになります。
price >= 0 and price <= budget間違いではありません。ただ Python には、これを数学の式そのままの見た目で書ける記法があります。
0 <= price <= budgetこれを 連鎖比較 と呼びます。多くのプログラミング言語では書けない、Python の気持ちのよいところです。
数学で
0 ≦ x ≦ 10と書くのと同じ形がそのまま通ります。読み手にとって意味が一瞬で分かるので、範囲の判定はこの形を優先します。
連鎖比較の中身
0 <= price <= budget は、内部的には 0 <= price and price <= budget と同じ意味に展開されます。つまり 両方の条件を満たしたときだけ True です。
price = 500
budget = 3000
print(0 <= price <= budget) # True
price = 5000
print(0 <= price <= budget) # Falseand に展開されるので、真ん中の price は 1 回しか評価されません。関数呼び出しを真ん中に置いても二重に呼ばれない、という利点もあります。
3 つ以上つなぐこともできます。0 <= a <= b <= 100 のような書き方も通りますが、長くなるほど読みにくくなるので、2 段までにとどめるのが実用的です。
演算子の優先順位
式の中に複数の演算子が混ざったとき、どれから計算されるかは決まっています。強い順に並べると下記のとおりです。
- かっこ
() - 掛け算・割り算
*///% - 足し算・引き算
+- - 比較
<<=>>===!=innot in notandor
算数の演算が先、次に比較、最後に論理演算という 3 段構えです。この順番のおかげで、下記の式はかっこなしで期待どおりに動きます。
total = 1200
budget = 3000
print(total * 2 > budget and total > 0) # Truetotal * 2 の 2400 が先に出て、2400 > 3000 は False、total > 0 は True、False and True で False。落ち着いて上から段を降りれば読めます。
迷ったらかっこ
優先順位は覚えるに越したことはありませんが、実務では 迷ったらかっこを付ける のが正解です。かっこは実行速度をほとんど変えず、読み手の負担だけを減らします。
# 動きは同じだが、意図がはっきりする
(total > budget) or ((total > 0) and (category == "食費"))とくに and と or が混ざるときは要注意です。and のほうが強いので、A or B and C は A or (B and C) になります。(A or B) and C のつもりで書くと結果が変わります。
「動くから正しい」と「読めるから正しい」は別の話です。3 か月後の自分が読める式を書いてください。
動きを追ってみる
in_range(500, 3000) の流れを追います。
priceに500、budgetに3000が入る0 <= priceを評価してTrueになるprice <= budgetを評価してTrueになる- 両方
Trueなので全体がTrueになり、それが返る
in_range(-100, 3000) なら、1 つ目の 0 <= -100 が False になった時点で打ち切られ、False が返ります。マイナスの金額を弾けるので、入力チェックとして使えます。
よくある間違い
- 不等号の向きをそろえない —
0 <= price >= budgetと書くと、意味の分からない条件になります。範囲を表すときは向きをそろえます。 andとorの強さを逆に覚える —andのほうが強く、先にまとまります。混ぜるときはかっこを付けます。0 <= price <= budgetを0 <= price and <= budgetと書く —andの右側にも完全な条件が必要です。この形はSyntaxErrorになります。
やってみよう
関数 in_range(price, budget) を実装してください。price が 0 以上かつ budget 以下のとき True、そうでないとき False を返します。
return 0 <= price <= budget の 1 行で書けます。and を使った形でも正解ですが、まずは連鎖比較の書き味を試してみてください。price がちょうど 0 のときも、ちょうど budget と同じときも、どちらも範囲に含まれて True になります。
要件
- 関数名は in_range で、引数は price と budget の2つ
- price が 0 以上かつ budget 以下のとき True を返す
- 下限の 0 と上限の budget はどちらも範囲に含める
- 0 <= price <= budget の連鎖比較で書く(and を使った形でも可)
入出力例
in_range(500, 3000) → true
in_range(0, 3000) → true
in_range(3000, 3000) → true
in_range(3001, 3000) → false
in_range(-100, 3000) → false
in_range(0, 0) → true