おもこん

おもこんは「思いつくままにコンピュターの話し」の省略形です

Python初心者のお勉強ノート(4)if文とループ(while文、for文)

制御構造のうち、良く使われるだろうと思われるif文とwhiler文、for文について書きます。 また、int型のところで保留していた比較演算子についてここで解説します。

文と式

文はなんらかの処理を実行する単位です。 例えば

print(1+2)

は、全体として文です。 引数の値をディスプレイに出力するという処理を実行する文ですね。

文はその一部に式を含むことがあります。 カッコの中の1+2の部分は式です。 式は値を返します。 この場合は3(1+2の計算結果)を返します。

print文は引数で返された値を画面に表示するという働きをします。

  • 文:プログラムの処理の単位
  • 式:計算などをして値を返すもの

文の中に式が入ることはありますが、逆に式の中に文が入ることはありません。 文は値を返さないからです。

if文

if文は条件分岐の文です。 条件分岐とは、条件によって、処理を分ける(分岐)ということです。 例えば、次のプログラムをエディタで作成し、sign.py(.pyは拡張子)という名前で保存してください。

x=5
if x>0:
  print("positive")
else:
  print("non-positive")

ファイルを保存したフォルダで端末を開き、pythonで実行します。

PS C:> py sign.py
positive
PS C:>

プログラムを実行したときの動作を確認しましょう。

  • 変数xに5を代入する
  • ifの次は条件といわれる。この例ではx>0が条件。条件のところには式を書く。この場合、xは5であり、x>0は正しい
  • 正しいときはif文の次の文が実行される。画面にはpositiveの文字列が表示される(positiveは「正(の数)」という意味の英語)。else以下は実行されない

最初の文を変えて、xに負の数-5を代入すれば、条件の次の文は実行されず、else以下の方が実行され、non-positive(非正)が表示されます。

この全体をif文といいます、 if文は、条件が正しいか正しくないかによって、異なる文を実行すします。 if文を書く時の注意点

  • if (条件式) : を書く。通常は1行だが、2行以上も可。最後にコロン(:)を忘れずに。コロンが条件式の終わりを意味する
  • インデント(字下げ、行頭に空白を入れること)をつけて、条件が真のときの実行文を書く。Pythonでは空白4文字のインデントが推奨されている。しかし、インデントがネスト(入れ子)になり長くなりすぎることを避けるならば空白2文字が良いだろう。実行文は2行以上になっても良いが、すべてに同じインデントをつけること。同じインデントの文をまとめてスイートと呼ぶ
  • else : を書く。コロンを忘れずに
  • 条件式が偽の時の実行文のスイートを書く。スイート内の各行は同じインデントにする。

スイートというのは複数の文をまとめたものです。 他の言語ではスイートの始まりと終わりをカッコで示したり、キーワードで終わりを示しますが、Pythonではインデントが同じ部分をスイートとします。 したがって、インデントには気を付けてください。

条件

条件のところには式を書きますが、その多くは比較演算でしょう。 例えば

if x > 0:

この中の「x>0」が比較演算です。 これは式なので、値を返します。 では、どのような値を返すのでしょうか。 この値は整数や文字列とは違う種類のオブジェクトで、True(真)またはFalse(偽)です。 プログラムにこれらのオブジェクトを書くとき、最初の文字が大文字で、残りは小文字でなければなりません。 これをBoolean型のオブジェクトといいます。 Boolean型にはTrueとFalseの2つしかありません。

このことから、if文は

  • 条件の返す値がTrueならば、条件の次の文(またはスイート)を実行する
  • 条件の返す値がFalseならば、else以下の文(またはスイート)を実行する

という仕組みになっていることが分かると思います。

実は、if文の条件がBoolean型以外を返すケースもあるのですが、それはここでは略します。

if文のネストとelif

if文はネスト(入れ子)にすることができます。 ネストとは、その文の中にもう一つの同じタイプの文を入れることです。

例えば、xが2桁の数かどうかを調べるプログラムを考えていましょう。 この場合、2つの条件分岐が必要です。

  • xが10以上か
  • xが100より小さいか

この2つを満足すれば2桁であるといえます。

x = 50
if x < 10:
  print("一桁または負の数")
else:
  if x < 100:
    print("二桁の数")
  else:
    print("三桁以上の数")

このプログラムのelseの中にif文が入ってネストを作っています。 このような場合、elifを使うとすっきりとした形に表せます。 elifはelseとifを合わせたもので、else(外側の条件が成り立たない)かつif以下が成り立つときに実行されます。

if x < 10:
  print("一桁または負の数")
elif x < 100:
  print("二桁の数")
else:
  print("三桁以上の数")

このプログラムの意味は

  • x<10であれば「一桁または負の数」を表示する
  • そうではなくて、かつ、x<100ならば、「二桁の数」を表示する
  • そうでなければ、「三桁以上の数」を表示する

となります。 「そうではなくて、かつ、○○ならば」を表すのがelifです。 elifを使うと場合分けをきれいに表現できることが多いです。 elifは万能ではないが、有用です。

while文

while文は条件が成り立つ間スイートを繰り返します。 例えば、次のプログラムは1, 2, 3, 4, 5を順に表示します。

x = 1
while x <= 5:
  print(x)
  x += 1
  • 変数xに1を代入する
  • while文の条件はx <= 5すなわちxが5以下であること。これが真である間は、次のスイートを実行する
  • スイートでは、まずxを表示する。xは1なので、1が表示される。次にxを1だけ増やす。xは2になる
  • 再びwhileの条件に戻り、x <= 5を評価する。このときxは2なので、条件は真で、次のスイートが実行される
  • スイートではxを表示する。xは2なので、2が表示される。次にxを1だけ増やす。xは3になる
  • 同様のことを繰り返すと、x=5までスイートは実行され、x=6になったときにwhileの条件x <= 5が偽になり、while文は終了する

この仕組みを使うと、好きな回数だけ同じことを繰り返すことができます。 しかし、この構造は、whileの条件文とスイート内のxを1だけ増やす文(x += 1)の2つが組み合わさってできており、その2つが離れた場所に書かれると分かりにくくなります。 うっかりxを増やすのを書き忘れることはありそうなことです。 この問題を解決するにはあとで出てくるfor文を使う方法が良いです。

while文は柔軟性があるが、スイート内で条件の変数を変化させる必要があるので、分かりにくく、できれば使わない方が良いです。

for文

for文もループを作る文です。 while文と違い、for文はリストの各要素に対するループなので、非常に分かりやすいです。 例えば、1から5までを出力するプログラムは次のようになります。

a = [1, 2, 3, 4, 5]
for x in a:
    print(x)

変数xに配列の要素を次々に入れスイートを実行します。 要素が無くなったらループが終わります。 while文ではスイートの中でxを更新しなければなりませんでした。 for文ではその必要がなく、シンプルに書くことができます。

range

rangeは数字の列を表すオブジェクトです。 例えば、1から5までは、

range(1, 6)

と表します。 1以上6未満の整数、という意味です。

リストに似ていますが、リスト[1, 2, 3, 4, 5]が5つのデータを保持するのに対して、rangeは初期値、終了値、ステップの要素のみを保持し、必要に応じてそこから数字の列を取り出します。 そのため、メモリ効率が良いという利点があります。 range型もfor文で使うことができます。

for x in range(1, 6):
    print(x)

このように連続する数値でループする場合はrange型でスマートに書くことができます。

range型を返すrange関数は、

range(初期値, 終了値, ステップ)

で書くことができ、初期値からはじめて、ステップを加えながら進み、終了値の手前で終わる数列を表します。 初期値を省略した場合のデフォルトは0です。 ステップを省略した場合のデフォルトは1です。

例えば両方省略して終了値だけを与えると

range(5)

これは0から4までの数列を表すrangeオブジェクトになります。

回数を指定したループの書き方

以上を総合すると、「3回繰り返すループを書きたい」のように回数指定してループを書くには、次のような書き方が良いことがわかります。

for x in range(3):
  print("Hello world.")

これで「Hello world.」が3回出力されます。 このとき、変数xには順に0から2が代入されるのですが、ループの中のスイートではxを参照していません。 したがって、 xは(文法上)形式的に置かれていることになります。 このようなとき、Pythonではアンダースコア(_)を良く用います。 Pythonではアンダースコアを「特に参照することのない変数」という意味で使う慣習があります。 ですので、xのかわりにアンダースコアを使えば、このプログラムを読む人も、ループ内でそれが使われることはないことが分かり、より読みやすくなります。

for _ in range(3):
  print("Hello world.")