目次記事
前の記事
条件分岐
Pythonで条件に応じて動作を変える(条件分岐する)には、if文 または match-case 文を利用します。
比較演算子
条件分岐を実装するには、ある条件について「真(正しい)ならこの動き!偽(正しくない)ならこの動き!」のように書く必要があります。
これを実現するのが論理値型オブジェクトです。論理値型オブジェクトは、真と偽の二つの値のみを取ります。論理値型オブジェクトの生成には比較演算子というものを使用します。
比較演算子には次の種類があります。
| 比較演算子 | 概要 |
|---|---|
a == b |
a と b が等価かどうか |
a != b |
a と b が異なるかどうか |
a < b (a > b) |
a が b よりも小さい(大きい) |
a <= b (a >= b) |
a が b 以下(以上) |
a is b |
a と b が同一のオブジェクトを参照しているかどうか |
a is not b |
a と b が異なるオブジェクトを参照しているかどうか |
a in b |
イテラブルオブジェクト b に要素 a が含まれるかどうか |
a not in b |
イテラブルオブジェクト b に要素 a が含まれないかどうか |
ではいくつか使ってみましょう。
>>> a = 3
>>> b = 3
>>> a == b
True
>>> a != b
False
>>> 1 < a < 10
True
>>> a in range(10)
True
>>> a = [1, 2]
>>> b = [1, 2]
>>> a == b
True
>>> a is b
False
ちょい発展な折りたたみ。等値と等価の話
is は「等値かどうか」、== は「等価かどうか」 を調べます。一見同じに見えますが、これらは厳密に異なります。
等値 とは、その変数に格納された数値が同じかどうかを調べます。値が等しいって意味です。例えば、a = [1, 2] と書いたとき、変数 a には 「[1, 2] というリストオブジェクトがあるメモリのアドレス」が入ります。調べるには id 関数を使用します。
>>> a = [1, 2]
>>> id(a)
1836050998272
たとえ、[1, 2] というリストオブジェクトの中身が同じでも、オブジェクト自体は異なります。なので別の変数に [1, 2] というリストオブジェクトを参照させると、id 関数の戻り値は変わります。
対して等価とは、「クラスの作成者が定める基準で、等しいかどうか」を調べるものです。
クラスについてはのちに扱いますが、オブジェクトを作るための設計図くらいに思っておいてください。等価の基準はクラス(設計図)を作った人が、「まぁココとココが等しいなら、同じって言っていいんじゃね?」と定めます。
例えば、リストオブジェクトを作成するための設計図である list クラスでは、
「要素が持つ値とそのインデックスが同じなら、等価である」
と定められています。
>>> a = [1, 2]
>>> id(a)
1836050998272
>>> b = [1, 2]
>>> id(b)
1836050990464
>>> a == b # 違うオブジェクトだけど等価ではある
True
>>> a is b # 違うオブジェクトなので等値ではない
False
Java やってる人は混乱するかもですね![]()
論理演算子
論理値型オブジェクト同士の演算では、論理演算子というものを使用します。論理演算を行った結果はまた論理値オブジェクトになります。
| 論理演算子 | 役割 |
|---|---|
P and Q |
P と Q がどちらも真なら真となる。それ以外は偽。 |
P or Q |
P と Q がどちらも偽なら偽となる。それ以外は真。 |
not P |
P の真理値を反転させる。 |
これらの論理演算子の和名は、and が論理積、or が論理和、not が否定です。
実際に出てきてから用法を確認しましょう。
条件式
条件によって値を分岐させる演算子が条件式と呼ばれるものです。
三項演算子と言っても伝わりやすいですが、Python では 3 つのオペランドを取る演算子がこれ一つではない(シーケンスのスライス)ので、正確には条件式といったほうがいい気がします。
とはいえ、シーケンスのスライスは確かに3つのオペランドを取るけど、演算子の役割は果たしてない気がするので、三項演算子って言っても問題ない気もする。難しいですね言葉って。
条件式の文法は次の通りです。
値1 if 論理値 else 値2
上記の文を実行すると、「論理値が真なら値1を、偽なら値2を実行する」という動きになります。
>>> a = 2
>>> msg = "aの値は1です" if a == 1 else "aの値は1ではないです"
>>> print(msg)
aの値は1ではないです
>>> name = "Yamada"
>>> msg = "あなたは山田さん" + ("です" if name == "Yamada" else "ではないです")
>>> print(msg)
あなたは山田さんです
複数の条件式を重ねることも可能です。
>>> hour = 17
>>> print(("おはよう" if 5 <= hour <= 9 else
... ("こんにちは" if 10 <= hour <= 17 else "こんばんは"))
... + "\nいつでも眠いです")
こんにちは
いつでも眠いです
if文
条件分岐を行う場合、if文というものも便利です。条件式では複雑な処理ができませんでしたが、if文であれば任意行数の工程を踏む処理を書くことができます。
if文の文法は次の通りです。
if 論理値1:
処理1
elif 論理値2:
処理2
else:
処理3
-
論理値1を見て、これが真なら処理1を実行。 -
論理値1が偽なら次のelif句を見ます。elif句の論理値2が真なら処理2を実行。 - 全ての論理値が偽の時、
else句の処理3を実行。
という流れで処理を進めます。elif 句、else 句は必須ではありません。
いくつか実例を見ておきます。
>>> err = ""
>>> err += "エラー1発生!"
>>> if err != "":
... print("エラーが発生しました。処理を中断します")
...
エラーが発生しました。処理を中断します
>>> hour = 18
>>> if 5 <= hour <= 9:
... print("朝です。おはようございます。")
... elif 10 <= hour <= 17:
... print("昼です。こんにちは。")
... else:
... print("夜です。こんばんは。")
...
夜です。こんばんは。
match-case文
Python3.10 から、match-case文という文が新登場しました。
match-case文は次の文法で使用します。
match 式:
case オブジェクト1:
処理1
case オブジェクト2:
処理2
case _:
処理3
-
matchの後には何かしらの式を書きます。ここに書いた式が参照するオブジェクトによって条件分岐します。 -
caseのあとには式が参照するであろうオブジェクトを記述します。例えば上の例で、matchの後の式がオブジェクト1と等価なオブジェクトを参照しているなら、処理1を実行します。 -
case _:はワイルドカードパターンで、それまでのすべてのcaseにマッチしなかった場合に実行する処理を記述します。
また、複数の case を並べたい場合は | で並べます。match-case文を使用するうえで注意する点は、「式とオブジェクトが等価かどうかで実行する case が変わる」という点ですね。等値ではなく等価です。
実際にやってみましょう。
>>> coin = 50
>>> match coin:
... case 1:
... print("1円玉です")
... case 5:
... print("5円玉です")
... print("ご縁がありますように")
... case 10:
... print("10円玉です")
... case 50:
... print("50円玉です")
... print("めっちゃ縁がありますように")
... case 100:
... print("100円玉です")
... case 500:
... print("500円玉です")
... print("コイツ20枚で1万円っていまだに不思議に感じる")
... case _:
... print(f"{coin}円の硬貨は日本にありません")
...
50円玉です
めっちゃ縁がありますように
>>> coin = 14
>>> match coin:
... case 1:
... print("1円玉です")
... case 5:
... print("5円玉です")
... print("ご縁がありますように")
... case 10:
... print("10円玉です")
... case 50:
... print("50円玉です")
... print("めっちゃ縁がありますように")
... case 100:
... print("100円玉です")
... case 500:
... print("500円玉です")
... print("コイツ20枚で1万円っていまだに不思議に感じる")
... case _:
... print(f"{coin}円の硬貨は日本にありません")
...
14円の硬貨は日本にありません
複数の処理を一つのブロックでまとめて行いたい場合、それらの処理のインデントをそろえる必要があります。
まとめたい処理のインデントをそろえるというルールは、オフサイド・ルール、またはレイアウト・ルールと呼ばれます。
ちなみに、有名な言語の多く(例えば C, Java, PHP, JavaScript, Go 等)は、波かっこ { } を使ってまとめたい処理を記述します。
【個人的な感想】逆にオフサイド・ルールを採用していて有名な言語って、Python と Ruby と Haskell と...、日本ではなでしことか?くらいしか思いつきませんわ。
case との比較は等価かどうかで行われます。なので次のようにリストオブジェクトなどを渡すことも可能です。
>>> holiday_list = []
>>> match holiday_list:
... case ["土", "日"]:
... print("うらやましい!")
... case ["日"]:
... print("まぁそんなもんよな...")
... case []:
... print("えぐすぎ")
... case _:
... print("シフト制とかかな!")
...
えぐすぎ
>>> holiday_list = ["土", "日"]
>>> match holiday_list:
... case ["土", "日"]:
... print("うらやましい!")
... case ["日"]:
... print("まぁそんなもんよな...")
... case []:
... print("えぐすぎ")
... case _:
... print("シフト制とかかな!")
...
うらやましい!
だいたいこれくらい知っておけば条件分岐は書けるようになるでしょう。今後もたくさん現れるので実際に使ってみて覚えていきましょう。
次の記事
作成中...