前回までで、プログラミングの主要な処理である「繰り返し」と複数のオブジェクトをまとめて扱う「リスト」を使ってくじびき対話システムを作成しました。繰り返し処理を行うwhile文を使うことで、対話システムらしいプログラムが作成できることを実感いただけたかと思います。

while文は繰り返し処理を柔軟に書けるのですが、リストなどの「要素」に対する繰り返し処理を記述しようとすると冗長になる傾向にあります。そこで、Pythonではそうした場合に便利な「for文」を用意しています。

今回はこのfor文を使って、ユーザーの質問に対して答えを返してくれるQA対話システムを作成してみましょう。動作イメージは以下の通りです。

ユーザーの質問(入力) 東京の区っていくつあるの?
システムの回答(出力) 東京都には23の区があります。

QA対話システムの概要

今回作成するQA対話システムでは、ユーザー発話に対してあらかじめ用意した質問回答リストから近い質問を探し出し、それに対応する回答をシステム発話として返します。

例えば、次のような質問回答リストがあるとします。

質問 回答
富士山の高さは? 富士山の高さは3,776mです。
東京都には区がいくつあるの? 東京都には23の区があります。

このとき、ユーザーが「富士山の高さって?」と発話(入力)すると、対話システムは質問回答リストを上から順にチェックして、ユーザー発話に近い「富士山の高さは?」という質問を見つけます。そして、その質問に対応する回答「富士山の高さは3,776mです。」をシステム発話として返します。

もし質問回答リストにユーザー発話に近い質問が見つからない場合は、「すみません、わかりません。」と返します。

また、「ありがとう」を含むユーザー発話が入力されると、「ありがとうございました。また質問してくださいね!」と返答してプログラムを終了します。

なお、今回の作業ディレクトリは「C:\Users\user\Documents\pychat\qa」としますので、事前に作成しておいてください。

それでは早速、作成していきましょう!

for文による繰り返し処理

for文は、次のような書式でリストの要素を順に変数に束縛し、続くインデントされた行でその変数を使った処理を記述します。

for 変数 in リスト:
    変数を使った処理

例えば、次のようなプログラムを考えてみましょう。

# names_for.py - 名前を要素に持つリストの表示プログラム
names = ["阿部", "佐藤", "田中"]

for name in names:
    print(name)
print("for文終了")

このプログラムでは、2行目で「names」という「名前(ここでは、阿部、佐藤、田中)」を要素に持つリストを定義しています。そして、4~5行目でfor文を使ってその名前を順に表示しています。

より詳しく言うと、まず初めて4行目のfor文までたどり着くと、リストnamesの1番目の要素「阿部」を変数nameに束縛します。そして、続いてインデントされた5行目を実行し、その結果として「阿部」と画面に表示します。

インデントされた行の処理が全て完了すると、4行目のfor文に戻り、次はリストの2番目の要素「佐藤」を変数nameに束縛し、5行目を実行。その結果として、「佐藤」と画面に表示します。

それが終わると再び4行目のfor文に戻り、リストの最後の要素「田中」を変数nameに束縛して5行目を実行し、「田中」と表示します。

こうしてリストの全ての要素に対して処理を実行すると、for文を抜けて6行目の処理を実行し、「for文終了」と画面に表示します。

それではこのプログラムを「names_for.py」というスクリプト名で保存し、実行して動作を確認してみましょう。

$ python names_for.py
阿部
佐藤
田中
for文終了

期待した動作になっているようですね。

ところで、while文を紹介した際に登場した「break文」を覚えているでしょうか? break文は、繰り返し処理の中で使用できる記述で、処理がbreak文に到達するとその場で繰り返し処理を終了するのでしたね。for文でも、while文のときと同様にbreak文を使って繰り返し処理を終了することができます。

例えばnames_for.pyで、「佐藤」という名前が出てきたら繰り返し処理を終了したいとしましょう。その場合、次のようにif文を使い、変数nameの値が「佐藤」だった場合にbreakすると、そこで繰り返し処理を終了することができます。

# names_break.py - 「佐藤」という名前が出るまでリストの名前を表示するプログラム
names = ["阿部", "佐藤", "田中"]

for name in names:
    print(name)
    # 佐藤という名前が出たらfor文を終了する
    if name == "佐藤":
        break
print("for文終了")

それでは、このプログラムをnames_break.pyというスクリプト名で保存/実行して、挙動を確かめてみましょう。

$ python names_break.py
阿部
佐藤
for文終了

「佐藤」で繰り返し処理を終了しているため、「佐藤」の次の要素である「田中」は表示していません。

このように、for文を使うことでリストの要素に関する繰り返し処理を簡潔に書くことができます。

今回は、QA対話システムを作成するにあたって必要となるfor文による繰り返し処理を紹介しました。次回は、同じくQA対話システムを作成する上で必要となる「正規表現」について説明します。

著者紹介


株式会社NTTドコモ
R&Dイノベーション本部 サービスイノベーション部
阿部憲幸

2015年京都大学大学院理学研究科数学・数理解析専攻修了。 同年、NECに入社。 2016年から国立研究開発法人情報通信研究機構出向。 2018年より現職。 自然言語処理、特に対話システムの研究開発に従事。 毎日話したくなるAIを夢見て日夜コーディングに励む。
GitHub:https://github.com/noriyukipy