Pythonにおけるif文について解説!

この記事を書いた人
北爪 聖也

株式会社pipon代表取締役。 キャリアはADK(広告代理店)でテレビ広告運用をして残業120時間するが、ネット広告では自分の業務がAIで自動化されていることに驚愕する。そこで、機械学習受託会社に転職し、技術力を身につけた後、piponを創業。現在、製薬業界、大手監査法人、EC業界、様々な業界でAI受託開発事業を運営。

公開日:2019/9/27
更新日:2019/9/27
キーワード:Python if文 基本構文
文字数:6800(読み終わるまでおよそ11分)

この記事でわかること

  • 条件分岐で用いるif文
  • if文と関連する基本構文

はじめに

プログラミングの基本は「条件分岐」と「繰り返し」の制御構造で、データサイエンスの世界でよく使われるプログラミング言語であるPythonにおいても、その例外ではありません。

繰り返しのfor文については別でまとめていますので、今回は条件分岐で用いるif文および、関連する基本的な構文を見ていきます。

1. 条件分岐における基本構文

パンダの中のパンダさんによる写真ACからの写真

1) 条件に合えば実行するif文

if文を使うと、「もし~ならばAを実行する。そうでなければBを実行する。」というように、条件を満たしているかどうかで、処理を分岐させることができます。

Pythonでは他のプログラム言語と違い、インデント(字下げ)を使ってif文のブロックを解釈するので、注意が必要です。

本稿では、インデントは半角4文字で設定することとします。

まずは、if文の基本的な書式を見てみましょう。

if 条件式 :
    #インデントの開始(半角4文字下げ)
    ステートメント1
    ステートメント2
    ステートメント3
#インデントの終了(if文の終了)

「if 条件式 :」を書いたら改行し、条件式がTrueだったときに実行するブロックに処理Aを書きます。このとき、必ず字下げを入れる必要があります。

複数行の処理Aを入力したい場合は、字下げの文字数を同じにしなければなりません。字下げしないでステートメントを書くことで、if文が終了となります。

条件式がFalseならば、if文のブロックを実行しないで、以降のステートメントへ移ります。

if文の流れを図にすると、次のように表せます(図1)。

図1. if文の流れ

if文のコードの例を見てみましょう(例文1-1)。

<例文1-1>

a = -1

if a<0 :
    a=0

a = a*2
print(a)

#############

a = 4

if a<0 :
    a=0

a = a*2
print(a)
0
8

これは簡単な条件分岐で、aの値が負だったらaに0を代入してからaを2倍し(=0)、正だったら何もしないで、aを2倍していることが分かります。

2) 条件に合うときの処理と合わないときの処理 if ~ else文

1)項では、条件に合わないときは何も実行しないでif文を抜けていましたが、条件に合うときと合わないときで別々の処理をしたいことがあります。

そのときは、if ~ else文を使います。

if 条件式 :
    #処理A
    ステートメントa1
    ステートメントa2
else :
    #処理B
    ステートメントb1
    ステートメントb2
#インデントの終了 (if ~ else文の終了)

条件式がTrueのときは処理A、Falseのときは処理Bを実行します。if文のときと同様に、字下げで処理Aのブロックと処理Bのブロックをグループ化します。

処理Aと処理Bの字下げの文字数は、同じである必要があるので注意してください。

if ~ else文の流れを図にすると、次のように表せます(図2)。

図2. if ~ else文の流れ

if ~ else文のコードの例を見てみましょう(例文2-1)。

<例文2-1>

hr = 40
daten = 80

if hr+daten >= 100:
    print("一流打者です")
    
else:
    print("一流打者ではありません")
    
##################################################

hr = 30
daten = 30

if hr+daten >= 100:
    print("一流打者です")
    
else:
    print("一流打者ではありません")
一流打者です
一流打者ではありません

hrとdatenの合計が100以上であれば「一流打者です」、100未満であれば「一流打者ではありません」と表示するコードです。

前半は合計が120でTrueなので、Trueのブロックを実行しています。後半は合計が60でFalseなので、else:以下のブロックを実行しています。

3) 3つ以上の選択肢があるときの処理 if ~ elif ~ else文

if ~ elif ~ else文を使うことで、複数の条件式をつなげて処理方法を分岐することが可能です。

if 条件式 1:
    #処理A
    ステートメントa1
    ステートメントa2
elif 条件式 2:
    #処理B
    ステートメントb1
    ステートメントb2
else :
    #処理C
    ステートメントc1
    ステートメントc2
#インデントの終了 (if ~ elif ~ else文の終了)

条件式1がTrueなら処理Aを実行し、Falseなら条件式2を評価します。条件式2がTrueなら処理Bを実行し、Falseなら処理Cを実行します。

if ~ elif ~ elif ~ elif ~ elif ~ ・・・~ elseのように、elifを条件の数だけ挿入することで、複数の選択肢の処理が可能となります。

if ~ elif ~ else文の流れを図にすると、次のように表せます(図3)。

図3. if ~ elif ~ else文の流れ

if ~ elif ~ else文のコードの例を見てみましょう(例文3-1)。

<例文3-1>

from random import randint
hr = randint(0,60) #0~60の乱数

if hr >= 50:
    batter = "よっ!ホームラン王!"

elif hr >=20:
    batter = "よっ!強打者!"
    
else:
    batter = "もうちょっとホームランを打ってくれよ~"
    
print(f"ホームラン{hr}本なので、{batter}")
ホームラン4本なので、もうちょっとホームランを打ってくれよ~

このコードは、ホームラン数を0~60本の間でランダムに決め、50本以上、20本以上、20本未満で表示を変えるコードです。

判定結果は変数batterに格納し、if ~ elif ~ else文を抜けた後で出力します。

4) if文のネスティング

if文の中でさらにif文を使うことで、より複雑な分岐ができます。if文を入れ子にして使うことを、ネスティングと言い、そのような構造をネスト構造入れ子構造と言います。

例文4-1は、ホームランが20本以上かつ、打点が80点以上の場合に、一流バッターと判定します。

<例文4-1>

#乱数を発生させるrandint関数をインポートする
from random import randint

hr = randint(0, 50) #0~50の乱数
daten = randint(10, 100) #10~100の乱数

#判定式
if hr >= 20 :
    if daten >= 80:
        kekka = "よっ!一流バッター!"
    else:
        kekka ="う~ん。がんばれ!"
    
else:
    kekka ="う~ん。がんばれ!"
    
#結果の出力
print(f"ホームランが{hr}本、打点が{daten}点なので、{kekka}")

(何回か繰り返した結果例)

ホームランが46本、打点が79点なので、う~ん。がんばれ!
ホームランが15本、打点が95点なので、う~ん。がんばれ!
ホームランが24本、打点が89点なので、よっ!一流バッター!

まず、最初のif文でホームラン(hr)が20本以上の条件式を判定します。この結果がTrueなら、さらに内側のif文で打点(daten)の条件式を判定します。

この流れを、図4に示します。

図4 ネスト構造の流れ

if文のネスティングは、流れに沿った素直な書き方ではありますが、複雑で間違えやすい書き方でもあります。

条件式で論理演算子を使うと、すっきりしたコードになりとても読みやすくなります。論理演算子を使ったif文は、7)項で述べます。

5) 比較演算子を用いた条件式の作成

if文は条件分岐の構文なので、比較演算子を用いて条件式を作成するのが一般的です。そこで、比較演算子を詳しく見ていきます。

aとbが等しいか、aがbより小さいか、bより大きいかといった比較を行う演算は、比較演算子で行います。

例えば、変数aとbに入っている値が等しいかどうかは、a==bの式で比較できます。比較した結果、等しければTrue、等しくなければFalseになります。=ではなく、==であることに注意してください。=は代入を意味します。

比較演算子をまとめると、表1になります。

表1. 比較演算子のまとめ

演算子説明
==a==baとbが等しいときTrue
!=a!=baとbが等しくないときTrue
>a>baがbより大きいときTrue
>=a>=baがb以上のときTrue
<a<baがbより小さいときTrue
<=a<=baがb以下のときTrue

では、比較演算子を用いた条件式で、if文を作ってみましょう(例文5-1)。

<例文5-1①>

a = 0

if a == 0:
    print("aは0です")
aは0です

<例文5-1②>

a = 1

if a != 0:
    print('aは0ではありません')
aは0ではありません

=は演算子ではなく、代入を意味しますので、条件式で使うとエラーとなってしまいます(例文5-2)。

<例文5-2>

a = 0

if a = 0:
    print("aは0です")
 File "<ipython-input-20-2f6f95760a65>", line 3
    if a = 0:
         ^
SyntaxError: invalid syntax

リストを比較する条件式を作りたい場合は、値が同じなのか、オブジェクトが同じなのかの、2通りの比較の仕方があります。

値が同じかどうかを比較する場合は、==演算子など表1の比較演算子を使い、オブジェクトが同一かどうかを比較する場合は、is、is notの演算子を使います(表2)。

表2. オブジェクトを比較する演算子のまとめ

演算子説明
isa is baとbが同一のオブジェクトのとき True
is nota is not baとbが同一のオブジェクトでないとき True

では、オブジェクトを比較する演算子を用いた条件式で、if文を作ってみましょう(例文5-3)。

<例文5-3>

a = [3, 5, 8]
b = [3, 5, 8]

if a is b:
    print("同じオブジェクトです")
    
else:
    print("違うオブジェクトです")
違うオブジェクトです

aとbのリストの要素は全く同じですが、オブジェクトが異なるため、条件式に対してはFalseが返されます。

ここで、演算子を==にすれば、値は同じなのでTrueが返されることになります(例文5-4)。

<例文5-4>

a = [3, 5, 8]
b = [3, 5, 8]

if a == b:
    print("要素は同じです")
    
else:
    print("要素は違います")
要素は同じです

オブジェクトが同じとは、以下のような場合です(例文4-5)。

<例文5-5>

a = [3, 5, 8]
b = a

if a is b:
    print("同じオブジェクトです")
    
else:
    print("違うオブジェクトです")
同じオブジェクトです

リストの比較を条件式で行う場合、要素を比較するのか、オブジェクトを比較するのかを間違えないようにしてください。

6) リスト内包表記におけるif文の使い方

リスト内包表記はPython独特の記述方法の一つです。リスト内包表記とは、[ ]の中に構文を書いて、イテラブルなオブジェクトから新しいリストを作る表記方法です。

ここでイテラブルとは、値に含まれている要素を、順に1個ずつ取り出すことができるオブジェクトのことです。

構文にはfor文が使われることが多いですが、if文の条件式を記述する例も多いので、その表現方法を見ていきます。

[for 変数 in イテラブル if 条件式 ]

では、リスト内包表記にif文を含んだコードの例を見てみましょう(例文6-1)。

<例文6-1>

suji = [45,25,34,75,12,50]

kekka = [dat for dat in suji if 30<=dat<50]

print(kekka)
[45, 34]

例文6-1では、6つの数値が入ったリストから、30以上50未満の数値のみを取り出して、リストに格納しています。

例文6-1を内包表記を使わずに書くと、例文6-2になります。

<例文6-2>

suji = [45,25,34,75,12,50]

kekka = []

for dat in suji:
    if 30<=dat<50:
        kekka.append(dat)
        
print(kekka)
[45, 34]

内包表記を使うことで、コードを簡素化できることが分かります。

7) 論理演算子を用いた条件式

if文の条件式で、複雑な条件分岐を行いたい場合、論理演算子(and、or、not)を使うと、コードを簡素化できることが多いです。4)項で述べたネスト構造も、論理演算子を使うことですっきりしたコードにできます。

まずは、論理演算子をまとめました(表3)。

表3. 論理演算子のまとめ

演算子説明
anda and b論理積。aかつbがTrueのときTrue。どちらかがFalseならFalse。
ora or b論理和。aまたはbのどちらかがTrueのときTrue。両方ともFalseのときFalse。
notnot a否定。aがTrueのときFalse。aがFalseのときTrue。

論理演算子の働きを見るため、TrueとFalseをそのまま使って確認してみます(例文7-1)。

<例文7-1>

#and演算子

print(True and True)

print(True and False)
True
False
#or演算子

print(True or True)

print(True or False)

print(False or False)
True
True
False
#not演算子

print(not True)

print(not False)
False
True

以上が、論理演算子の使い方です。

では、and演算子を使って、if文を作ってみましょう(例文7-2)。なお、このコードは4)項のネスティングで用いた、例文4-1を論理演算子を使って書き直したものです。

<例文7-2>

#乱数を発生させるrandint関数をインポートする
from random import randint

hr = randint(0, 50) #0~50の乱数
daten = randint(10, 100) #10~100の乱数

#判定式
if (hr >= 20) and (daten >= 80):
    kekka = "よっ!一流バッター!"
    
else:
    kekka ="う~ん。がんばれ!"
    
#結果の出力
print(f"ホームランが{hr}本、打点が{daten}点なので、{kekka}")

(何回か繰り返した結果例)

ホームランが46本、打点が79点なので、う~ん。がんばれ!
ホームランが15本、打点が95点なので、う~ん。がんばれ!
ホームランが24本、打点が89点なので、よっ!一流バッター!

例文4-1と同じく、ホームランが20本以上かつ、打点が80点以上の場合だけ、一流バッターになるように判定されています。

しかし、例文4-1に比べるとコードがすっきりしており、読みやすくなっていることが分かります。

シンプルなコードを書くためにも、論理演算子の使い方を覚えておいてください。

次に、or演算子を使ったif文を見てみましょう(例文7-3)。

<例文7-3>

#乱数を発生させるrandint関数をインポートする
from random import randint

hr = randint(0, 50) #0~50の乱数
daten = randint(10, 100) #10~100の乱数

#判定式
if (hr >= 20) or (daten >= 80):
    kekka = "いいんじゃない!"
    
else:
    kekka ="う~ん。がんばれ!"
    
#結果の出力
print(f"ホームランが{hr}本、打点が{daten}点なので、{kekka}")

(何回か繰り返した結果例)

ホームランが18本、打点が98点なので、いいんじゃない!
ホームランが26本、打点が44点なので、いいんじゃない!
ホームランが12本、打点が58点なので、う~ん。がんばれ!

ホームランが20本未満かつ、打点が80点未満の時、がんばれと判定されています。

2. おわりに

今回は、Pythonプログラミングの条件分岐に必須である、if文および関連する基本構文について述べました。

データ解析の際は、条件に合うデータのみデータベースから取り出すというように、条件分岐と繰り返しを使って、解析用のデータベースを作成したい場面が出てきます。

今回述べたif文は、条件分岐の基本となる構文なので、しっかり理解しておいてください。

3. 参考サイト

Pythonのif文と比較演算子(等しい、大きい、以上など)
http://www.irohabook.com/python-equal

Pythonのif文による条件分岐の書き方
https://note.nkmk.me/python-if-elif-else/