条件を満たすまで無限に処理するループ

Python
Photo by Nothing Ahead from Pexels

前回はリストと繰り返し処理を見てきました。

今回はループ(for文)の補足と繰り返し処理2(while文)を学びます。

次回は画像処理について説明します。

JUVET
JUVET

以前作成したノートブックにコードを追加していきます!

ループ(for文)の補足

for文を使わないで繰り返し処理を実装する

前回のプログラムをもう一度見てみましょう。

test_list = ['おはよう', 'こんにちは', 'こんばんは']

for text in test_list:
  print(text)


これがどのような振る舞いをするかは前回説明したとおりです。
しかし、実行される処理の順番が分かりづらかったかと思います。

ここでは、あえて for文を使わないで実装します。
上記プログラムと同じ処理を実現するなら以下のようになります。

# まずはリストを用意
test_list = ['おはよう', 'こんにちは', 'こんばんは']

# リストの1つめの要素を変数textに代入
text = test_list[0] # textに'おはよう'が入る
print(text)

# リストの2つめの要素を変数textに代入
text = test_list[1] # 'おはよう'が'こんにちは'に上書きされる
print(text)

# リストの3つめの要素を変数textに代入
text = test_list[2]
print(text)
出力: 
おはよう
こんにちは
こんばんは


ここで print(text) で出力される文字列に注目してください。
‘おはよう’ 、’こんにちは’ 、’こんばんは’ の順番で出力されているため、
プログラムは上から順に実行されていることが確認できますね。

つまり、プログラムが実行される順番は原則「上から順に」です。

JUVET
JUVET

プログラムは上から順に(一行づつ)実行されます!


しかし、for 文ではこの当たり前の感覚とは少しズレたことが起きてしまい、
途端に苦手意識を持つ方が出てきてしまいます。

実は for 文を使ったループでは、
インデントされた処理を実行した後、
再び for 文の先頭に戻るため、分かりづらくなるのです。

なので for 文はこのように理解しましょう。

  1. test_list(リスト)の中にある最初の要素を text(変数)に代入し、何らかの処理をする
  2. 次の要素が存在する場合、その要素を text に代入し、処理を繰り返す
for text in test_list:
  処理

※ 今回は変数名が text でしたが、ここで使用する変数名は自由に変えられます。


イテラブル(繰り返し可能)であればループ可能】

ループにはリストを使うという話をしましたが、
実はもう少し広く定義されており、
イテラブル(繰り返し可能)でさえあればいいのです。

コードを通してイテラブルを理解しましょう。

# 0~9のループ範囲をつくる
for i in range(10):
  print(i)
出力: 
0
1
2
3
4
5
6
7
8
9

※ これまでの for 文で使っていた変数名は text でしたが、
ここでは i (indexの略)としています。

JUVET
JUVET

for i in 〜という形はよく登場しますので、慣れていきましょう!

range( )関数は、繰り返しの範囲(range)を作りたいときに使う組み込み関数です。

使い方は、引数につくりたい範囲の数字を指定するだけです。
つまり、
繰り返し処理で要素を何回取り出したいかによって、
カッコの中に書く数字を変えるということです。

前回、プログラミングは 0 スタートが基本という話をしましたが、
この range( )関数も例に漏れず、上記コードのように範囲10をつくる場合、
そのスタート地点は 0 になるため、
つくり出される範囲としては 0〜9 になります。

この例のように要素を順番に取り出せて、
繰り返し可能であるデータ型の性質のことをイテラブル(iterable)といいます。

たとえば、以下の変数(test_variable)はイテラブルではないため例外を発生します。

# 整数を用意
test_variable = 150 # variableは変数という意味

# in の後にくる変数がintデータ型になっているため、例外が発生
for v in test_variable:
  print(v)
出力: 
TypeError: 'int' object is not iterable

この変数の場合データ型(Type)がint データ型であるため、
上記のような例外を発生します。
「’int’ object is not iterable」は int データ型がイテラブルでないことを示しています。
つまり、
整数というデータ型は繰り返し可能なデータ型ではないということです。

現時点で何がイテラブルかはまだ理解できなくても問題ありません。
しかしながら、ループ(for文)を使うときは、
in の後にくる変数がイテラブルでなければならないことは覚えておくようにしましょう。

JUVET
JUVET

ひとまずリストを指定しておけば間違いありません!


ちなみに、文字列はイテラブルなので文字が一個づつ取り出されます。

test_text = '文字列はイテラブルです。'

for t in test_text:
  print(t)
出力: 

文
字
列
は
イ
テ
ラ
ブ
ル
で
す
。

イテラブルとして指定できるものはリスト、文字列の他に、
辞書(ディクショナリ)タプルとよばれるデータ型があります。
しかし、これらは現時点では使わないので、ひとまず説明は割愛します。

JUVET
JUVET

辞書に関しては次回説明します!


実はこの forループは1行にまとめられるので、
補足としてそちらも見ていきましょう。

内包表記とはfor文をコンパクトにまとめたもの

Photo by Harsh Jadav on Unsplash

たとえば、先ほどの range( )関数を使った
数字の平方(2乗)リストは次のように作成します。

squares = [i**2 for i in range(10)]

print(squares)
出力: 
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

for i in range(10) の部分はこれまでと同じです。
異なるのは for の左側で、
ここにはそれぞれの要素に対しての処理を書きます。

この場合、range( )関数で作られる数字一つひとつに対して、
二乗(i ** 2)の計算をしています。

流れとしては、まず数字の0が生成され、それが変数 i に代入されます。
ここまでは同じです。
そして i の二乗が計算され、リストの一つの要素として保存されます。
続いてrange( )関数で数字の1が生成され、その二乗が続く要素にカウントされます。
同様に他の数字でも同じ処理が実行されます。

また、右辺の [ ](角カッコ)を忘れないようにしましょう。
これがないとリストが作成されないので注意が必要です。
構文としては以下のようになります。

[式 for 変数 in イテラブルなデータ型]

このように、内包表記を使うとリストが簡潔に記述できるのです。
最初はこの書き方に違和感を覚えるかもしれませんが、
Python ではよく利用されますので、少しづつ慣れていきましょう。

次は for文とは異なる性質を持つループ(while文)を見ていきます。

終わりが見えない時に使うwhile文

Photo by Mars Plex on Unsplash

まず最初に思うこととしては、なぜループが2つもあるのかということでしょう。
これには理由がありまして、
for文の方は処理を実行する時点で、
何回繰り返すのかがあらかじめ分かっている時に使うのに対して、
while文はそれが把握できない時に使用するからです。

つまり、
while文は繰り返す回数は明確ではないけれど、繰り返し処理を実現したい時に使います。
たとえば次のような場面です。

1. Webカメラが起動している間はずっと(繰り返し処理を実行したい)
2. 想定する回答があるまでずっと(繰り返し処理を実行したい)

上記の例についてそれぞれ説明します。
1. の場合について、
これは例えばwebカメラを起動している間に人の顔が写っていたら、
エフェクトをかけ続けるといった場合を指します。

2. については、以前作成した年齢プログラムを例に説明します。
以前書いたコードには以下の欠点がありました。
数値以外が入力されると「数字のみを入力してください」と出力され、
プログラムが一度の実行で終了してしまう

age = input('あなたの年齢を教えてください。')

try:
  age = int(age)
  if age <= 19:
    print("お酒は20歳から。")
  else:
    print("お酒には気をつけましょう。")

except ValueError:
  print('数字のみを入力してください。')
出力: 
あなたの年齢を教えてください。test
数字のみを入力してください。

たとえば「test」と入力すると、
「数字のみを入力してください。」と出力され、プログラムが終了してしまいます。

しかし、実際には数字以外が入力された場合にはプログラムが終了するのではなく、
続けて同じ処理を繰り返してほしいはずです。

つまり、本当は数字のみを入力してほしいはずなので、
数字が入力された時は通常通り if or else 以下の処理が実行され、
この時はプログラムが終了するように設定し、
数字ではない場合には改めて「あなたの年齢を教えてください。」
と聞き返す(処理を繰り返す)ようにしたいということです。

今説明したことを満たすようなプログラムの例を以下に書きます。
前提として、try except 構文if else 構文の理解が必要です。

JUVET
JUVET

以前の記事で説明していますので、心配でしたら確認してください!

# 無限ループの作成(Trueなので常に条件が満たされ、永遠と繰り返し処理が行われる)
while True:
  age = input('あなたの年齢を教えてください。')

  try:
    age = int(age)
    if age <= 19:
      print("お酒は20歳から。")
    else:
      print("お酒には気をつけましょう。")
    break # 数字が入力された場合はループを終了

  except ValueError:
    print('数字のみを入力してください。')


まずは先頭の「while True: 」から見ていきます。
これから、
ある条件が満たされ続けている時に限り、繰り返し処理を行いたいとします。
そんな時は while というキーワードを使い、その隣に条件式、続けてコロンを書きます。
また、繰り返す処理はインデント以下に書きます。

今回は条件式として「True」を書いていますので、
この条件は常に満たされることになり、繰り返し処理が永遠に行われます。

永遠というのは文字通り、
PCの電源でも落ちない限りずっと処理が繰り返されることを意味します。
しかし、それでは困りますよね。
ある条件が満たされたときだけ、ループから抜けられるようにする仕組みがあれば便利です。

この機能を実装するには「break」というキーワードを使います。
上のコード例では、try 文以下の処理に書かれています。
つまり、数字が入力された時だけループから抜けられるようにしているということです。

条件が満たされたとき、ループから抜けだせるようにbreakキーワードを使う

以下のように数字を入力した場合、
プログラムは break にたどり着き、ループが(1回で)終了します。

出力: 
あなたの年齢を教えてください。23
お酒には気をつけましょう。


また、数字以外を入力すると繰り返し処理が何度も行われ、
input( ) 関数で指定した「あなたの年齢を教えてください。」が表示され続けることになります。
以下の例では、何回か数字以外を入力したもので、最後に数字を入力した例になります。

出力: 

あなたの年齢を教えてください。愛
数字のみを入力してください。
あなたの年齢を教えてください。2回目
数字のみを入力してください。
あなたの年齢を教えてください。このように
数字のみを入力してください。
あなたの年齢を教えてください。何度でも
数字のみを入力してください。
あなたの年齢を教えてください。繰り返し処理
数字のみを入力してください。
あなたの年齢を教えてください。が行われる
数字のみを入力してください。
あなたの年齢を教えてください。数字を入力すると終了する
数字のみを入力してください。
あなたの年齢を教えてください。23
お酒には気をつけましょう。

先ほど説明したように、この場合のループというのは、
いつ数字が入力されるか分からないため、繰り返す回数が決まっていないと判断できます。
そのため、for文ではなくwhile文の方が適しているといえるのです。

最後に予約語(キーワード)について説明します。

予約語とは予約席のようなもので自由には使えない

Photo by iOnix from Pexels

お気づきかもしれませんが、
今回 while文について解説する際に「キーワード」という言葉を使って説明しました。

実はこのキーワードというのは特別な意味を持っているため、適切な扱いが求められます。
見出しに書いてある通り、
予約語(キーワード)は予約席のようなものとして考えると理解しやすいと思います。

つまり、Pythonに、先に予約されていて、
その席(機能)を自由には使えないということです。
特定の単語(キーワード)は予約されているため、
勝手に使おうとすると例外が発生してしまうという仕組みです。

たとえば今回登場した while というキーワードを例に説明します。
この while は予約語なので、
その機能は「繰り返し処理」のみに制限されており、
それ以外の機能(例えば変数名として割り当てたいなど)には使えず、例外を発生します。

# while を変数名として使おうとした場合、例外が発生
while = 100
出力: 
SyntaxError: invalid syntax


「invalid syntax」と出力されているのは、構文が正しくないという意味ですが、
これはつまり、Python が while というワードに対して、
繰り返し処理という特別な意味を持たせているのに、
想定する構文以外の使い方をしようとしたから、
Python に「繰り返し処理の構文ではない」と解釈され、例外が発生するということです。

これまで構文として説明してきた if else 構文や try except 構文に含まれる単語なども
予約語なので、想定している文法(使い方)でしか機能しません。

まとめ

今回は whileループや予約語について学び、
無限ループから抜け出す break にも触れました。

range( ) 組み込み関数も登場しましたね。
この関数も今後よく目にすると思いますので、覚えておくと良いでしょう。

また、for文にはイテラブルを指定する必要があることや
内包表記を使うことで簡潔に記述できることもお伝えしました。

今回出てきたルールは以下の通りです。

ルール7: プログラムは上から順に実行される

内容についてご質問があればコメント欄からどうぞ

次回モジュールがどこから呼び出されているのか、
また関数の再利用法や(配布されている)プログラムを
どのようにして読み込むのかといった話をします。



【P.S.】
@AI_JUVETをフォローしていただけると大変励みになります🙂

コメント

タイトルとURLをコピーしました