Pythonの標準入力とは
標準入力とは、プログラムに外部からデータを渡す際に使われる共通の仕組みです。
キーボードから文字を入力したり、データファイルを渡したり、別のプログラムの出力を受け取ったりと、データの渡し方にはさまざまな方法があります。ただ、それぞれの方法にあわせた処理を実装するのは非常に大変です。
そこで、「標準入力」という共通の仕組みを利用します。標準入力を使ったコードを書いておけば、受け取る側のプログラムは必要なデータを適切に取り出せるのです。
【関連】Pythonをもっと詳しく学ぶならpaizaラーニング
Pythonにおけるinput関数の基本
Pythonで標準入力を扱う際は、input関数を使います。input関数は標準入力から1行分のデータを読み込み、文字列型(str型)の値として返します。
【関連】Pythonのstr型を基礎から学ぶ!初心者向け完全ガイド
例えば、入力にpaizaと書いて実行すると、paizaがそのまま出力されます。
# 入力
paiza
# 出力
paizainput関数が1回で読み込めるのは、標準入力の「1行」だけです。入力が複数行ある場合は、input関数を複数回呼び出すことで対応できます。2行の入力を受け取りたければ、次のように記述します。
# 入力
paiza learning
paiza.io
# 出力
paiza learning
paiza.io1行に半角スペースで区切られた複数の値がある場合も、input関数はその1行をまるごと文字列として受け取ります。上記の入力では"paiza learning"という1つの文字列として扱われます。個々の値に分解するには、あとからsplitメソッドを使う必要があります。
【関連】Pythonの空白処理をマスターしよう!strip・split・空白判定の使い方を徹底解説
なお、input関数は1行の末尾にある改行文字(\n)を取り除いた状態で値を返します。そのため、受け取った文字列をprint関数で出力しても、末尾に余分な改行が入ることはありません。
Pythonの標準入力(input関数)で受け取った値をint型・float型に変換する方法
input関数が返す値は、常に文字列型(str型)です。そのため、受け取った値を数値として計算に使うには、int関数やfloat関数で型変換する必要があります。
# 入力
813
# 出力
813標準入力から受け取った値の型変換は、 int(input()) のように1行にまとめて書くこともできます。
2つの整数値を受け取って和を求める場合は、次のように記述します。
# 入力
813
119
# 出力
n + m = 932このコードの処理の流れを追う前に、@simple_decorator という書き方が裏側で何をしているかを先に再確認しておきましょう。
say = simple_decorator(say)なお、input関数で受け取った文字列を変換せずに演算しようとすると、TypeErrorが発生します。また、 "3" + "5"のような文字列同士の+は文字列の連結になり、"35"が返ります。数値として計算する場合は、必ずint関数やfloat関数で変換してから演算してください。
小数点を含む数値を扱いたい場合は、float(input())とすることで、浮動小数点数型(float型)として受け取れます。
入力値をそのまま文字列として使いたい場合は、変換不要です。例えば名前や単語を受け取って出力する場合は、input()の結果がそのまま使えます。
また、型変換に失敗した場合はValueErrorが発生します。例えばint("hello")のように、数値に変換できない文字列を渡すとエラーになります。
以下の記事では型変換について詳しく解説しています。
【関連】Pythonのキャスト(型変換)とは?仕組みや使用例を具体的なコードで解説
Pythonの標準入力(input関数)で1行に複数の値がある場合の受け取り方・split関数の使い方
1行に半角スペース区切りで複数の値が入力される場合は、splitメソッドを使います。input().split()と書くことで、入力された1行を空白文字で区切り、各値を要素とするリストが生成できます。
# 入力
1 12 123
# 出力
['1', '12', '123']このとき、リストの各要素はまだ文字列型です。整数のリストとして扱いたい場合は、各要素をint関数で変換する必要があります。以下は、for文とappendメソッドを使う書き方です。
# 入力
1 12 123
# 出力
[1, 12, 123]splitメソッドに区切り文字を指定しない場合、半角スペースを含むすべての空白文字で区切ることができます。
「空白文字」には半角スペースだけでなく、タブ(\t)や改行(\n)、垂直タブ(\v)、復帰(\r)なども含まれます。カンマやスラッシュなどは空白文字ではないため、split(",")のように引数に区切り文字を指定する必要があります。
また、list(input())と書けば、入力された文字列の各文字を1文字ずつ分割したリストを得られます。例えばpaizaという入力なら、['p', 'a', 'i', 'z', 'a']が返ってきます。スペース区切りで値を分割したい場合との違いに注意しましょう。
なお、splitメソッドの結果はリスト型ですが、各要素はすべて文字列型となります。例えば['1', '12', '123']というリストを得ても、各要素はあくまで文字列の'1'・'12'・'123'です。整数として扱うには、for文や内包表記、map関数を使って各要素をint関数で変換する必要があります。
以下の記事ではリストについて詳しく解説しています。
【関連】Pythonのlistを徹底攻略!基本から実践応用まで初心者向けに解説
Pythonの標準入力(input関数)で内包表記とmap関数を使い処理する方法
Pythonには、より簡潔なコードでfor文を使ったリスト生成ができる「リスト内包表記」という構文があります。前のセクションで示したfor文のコードも、内包表記を使えば1行で書けます。
# 入力
1 12 123
# 出力
[1, 12, 123]内包表記の構文は、[式 for 変数 in イテラブル]です。int(x)が各要素になる式、for x in input().split()がループの部分に対応しています。
内包表記を使えば、複数行のfor文が1行にまとめられます。そのためコードが短く読みやすくなり、処理の意図も伝わりやすくなります。
また、map関数を使う方法もあります。map(関数, イテラブル)と書けば、イテラブルの各要素に指定した関数を適用した結果がmap型として返ってきます。splitメソッドで生成したリストの各要素にint関数を一括適用する場合は、次のように記述します。
map型は、そのままでは各要素を確認しにくいため、list関数でリスト型に変換するのが一般的です。
入力される値の個数があらかじめわかっている場合は、mapの結果を直接アンパック(展開)して複数の変数に代入できます。
# 入力
1 12 123
# 出力
1 12 123内包表記とmap関数のどちらを使うかは、状況と好みによります。特定の個数の値を変数に振り分けたい場面では、map関数+アンパックが便利です。一方で、個数が不定の場合やあとからリストとして処理したい場合は、内包表記でリストを生成したほうがよいでしょう。
また、map関数はint以外にも使えます。例えば、map(float, input().split())とすれば小数のリストを一括変換できます。さらに、map(str, ...)のように文字列変換にも応用できます。組み込み関数だけでなく自作関数も指定できるため、複雑な変換処理をシンプルに書きたいときにも便利です。
Pythonの標準入力(input関数)で内包表記を使い複数行をリストに変換する方法
「先頭行で入力の行数を受け取り、以降の行で各値を受け取る」というパターンについて解説します。
3
1
12
123この形式では、先頭行の3が「このあと3行の入力がある」ことを示しています。以下のようにfor文とrange(n)を組み合わせれば、入力値が何行あっても柔軟に対応できます。
# 出力
[1, 12, 123]先頭行で行数を受け取り、for文でrange(n)回ループすれば、複数行入力を処理できます。
この場合、先頭で受け取ったnに応じて処理回数が変わるため、入力が100行でも1000行でも同じコードで対応可能です。input関数を固定回数書くだけでは、行数が変わってしまえば対応できなくなります。上記のようなrange(n)を使ったfor文なら、柔軟に処理できます。
「先頭行で件数を受け取る」という入力パターンは、実務におけるCSVやログファイルを処理する場面でもよく見られます。
また、内包表記を使えばコードをさらに簡潔にできます。
内包表記の中でループ変数を使わない場合、Pythonの慣習としてアンダースコア_を使います。これは「文法上は必要だが、実際には使わない変数」であることを示す書き方です。決まりではなく慣習ですが、_を使えばコードを読んだ人が「このループ変数はループ回数の管理だけに使われている」とすぐに理解できます。なお_は「使わない変数」を意味する慣習のため、_ = 1のように代入して使うことは推奨されていません。
なお、以下の記事ではfor文とrangeについて詳しく解説しています。
【関連】Pythonのfor文を基礎から応用まで徹底解説!繰り返し処理の完全ガイド
【関連】Pythonのrangeの使い方を徹底解説!基本から応用まで
Pythonの標準入力(input関数)で複数行・複数列を内包表記で受け取る方法
以下のような複数行かつ各行に複数の値が含まれる場合も、内包表記を使えば簡潔に処理できます。
3
1 2 3 4
5 6 7 8
9 10 11 12for文を使った書き方は以下の通りです。先頭行で行数nを受け取り、各行の入力値をsplit()で分割してint()変換し、2次元リスト(リストのリスト)として格納します。
# 出力
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]上記は二重のfor文ですが、内包表記を使えば以下のように1行でまとめられます。
二重の内包表記を使えば、複数行・複数列の入力も2次元リストとして1行で受け取れます。
上記では、内側の[int(x) for x in input().split()]が1行分の入力を整数リストに変換する処理、外側のfor _ in range(n)がn回繰り返す処理を担っています。まず内側の処理を理解してから、外側を読み解けば構造を把握しやすいでしょう。この構造を理解しておけば、列数や行数が変わっても同じパターンで対応できます。
生成された2次元リストliは、li[0]で1行目、li[1]で2行目にアクセスできます。さらにli[0][0]のように2つのインデックスを使うと、特定の行・列の要素を取り出せます。
また、変数nの受け取りも内包表記の中にまとめることができます。
ただ、この書き方はコードを読み解くのに時間がかかる可能性があります。実務などで人と共有するコードの場合は、変数nを明示する書き方のほうが読みやすく、ミスも起きにくいでしょう。
2次元リストのパターンは、複雑に感じるかもしれません。その場合は、まずfor文でコードを書いて動作を確認し、慣れてきたら内包表記に書き直すのがよいでしょう。
Pythonで標準入力(input関数)を扱う際によくあるエラーと対処法
TypeError:型変換を忘れている
input関数が返す値は文字列型のため、そのまま数値の演算に使うとTypeErrorが発生します。
このエラーは、初心者が最もよく遭遇するエラーの一つです。エラーメッセージにstrやintという型名が出てきたら、型変換の漏れを疑いましょう。
ValueError:数値以外の入力をint関数に渡している
入力値が数値でない文字列をint関数に渡すと、ValueErrorが発生します。例えばint("abc")はエラーになります。入力形式を事前に確認し、小数が含まれる場合はfloat関数を使うなど、正しい型変換関数を指定しましょう。
splitメソッドの結果が期待と異なる
入力値の区切り文字がスペースではなくカンマの場合、引数なしのsplitメソッドでは正しく分割されません。区切り文字を明示して、split(",")のように指定してください。
入力形式(区切り文字・行数・データ型)を確認してから、適切な変換・分割処理を選ぶようにしましょう。
IndexError:想定より少ない入力値しかない
split()で分割した結果のリストをインデックス指定で参照する際、要素数が想定より少ないとIndexErrorが発生します。入力値の個数が、想定と一致しているかを確認しましょう。
また、map関数+アンパックで変数の数と入力値の個数が合っていない場合も、ValueError: not enough values to unpack というエラーが出ます。
標準入力に関するエラーの原因は、多くが「入力形式をよく確認していなかった」「型変換を忘れた」という2点に集約されます。入力形式・データ型・行数・区切り文字の4点を確認する習慣をつけると、エラーを未然に防ぎやすくなります。
よくある質問(Q&A)
Q. map関数とリスト内包表記は、どのように使い分ければよいですか?
A. どちらを使っても同じ結果を得られますが、以下のように使い分けるとコードより読みやすくなります。
- map関数が向いている場面:入力値の数が決まっている場合、複数の変数に直接代入(アンパック)したい場合# 例 a, b, c = map(int, input().split())
- リスト内包表記が向いている場面:入力値の数が変動する場合、最終的にリストの形でデータを保持してループ処理などを行いたい場合# 例 li = [int(x) for x in input().split()]
Q. 空白以外の文字(カンマやスラッシュなど)で区切られている場合は、どうすればいいですか?
A. split() メソッドの引数(カッコの中)に、区切りたい文字を文字列として指定してください。
- カンマ(,)区切りの場合:input().split(",")
- スラッシュ(/)区切りの場合:input().split("/")
引数を指定しない場合は、半角スペース、全角スペース、タブ、改行などのすべての空白文字が区切り文字として扱われます。
Q. paizaのスキルチェックや演習問題で、コードは合っているはずなのに「不正解」になってしまう原因は?
A. 以下の3点を確認してみましょう。
1.input関数の引数に案内メッセージを入れている
input("数値を入力してください:") のように記述すると、その案内メッセージもプログラムの出力(標準出力)とみなされ、「出力結果が一致しない(不正解)」と判定されます。解答をする際は、必ず引数を空( input() )にしましょう。
2.型変換(キャスト)を忘れている
input() で受け取る値は、常に文字列(str型)です。数値の計算を行う場合は、必ず int関数 や float関数 で型変換を行っているかを確認しましょう。
3. 行数やループ回数のカウントがズレている
複数行の入力処理で、先頭行の件数(n)を読み込んだあとのループ回数(range(n))や、データの読み込み回数に過不足がないかを確認しましょう。
Q. 大量の入力データを処理する際、実行時間を短くする(高速化する)方法はありますか?
A. 数万行を超える大量データを標準入力から読み込む場合、通常のinput関数では処理が間に合わず、時間切れ(Time Limit Exceeded)になることがあります。その場合は、sys モジュールの sys.stdin.readline を使って大幅に高速化できます。
プログラムの冒頭に以下のように記述しておけば、それ以降のinput関数の書き方(型変換やsplitなど)は変えずに、高速な読み込み処理に置き換えられます。
なお、sys.stdin.readline は、行末の改行文字(\n)を含んだまま文字列を読み込む点に注意しましょう。数値を int型 に変換する場合は、自動で改行が無視されるため問題ありません。ただ、文字列としてそのまま扱いたい場合は、 input().strip() のようにして改行を取り除く必要があります。
まとめ
Pythonで標準入力を扱う方法について、input関数の基本から複数行・複数列の応用パターンまで解説しました。
- input関数は標準入力から1行を文字列として受け取る
- 数値として扱う場合はint関数やfloat関数で型変換する
- 複数の値を1行で受け取るにはsplitメソッドを使う
- 内包表記やmap関数を使うとより簡潔なコードになる
- 複数行の入力は先頭行で行数を受け取りfor i in range(n)でループ処理するとよい
- 複数行・複数列の入力は2重の内包表記で2次元リストとして受け取れる
初めて標準入力に触れた方も、この記事で紹介した基本的な使い方を参考に、実際にコードを書いてみてください。
Pythonで標準入力を扱う方法はシンプルに見えますが、input関数の型・splitメソッドの区切り文字・型変換のタイミングなど、細かい落とし穴も多くあります。この記事で解説した内容を繰り返し練習すれば、どのパターンにも対応できるようになるでしょう。
なお、paizaラーニングの「新・Python入門編15:標準入力を理解しよう」では、実際にコードを書きながら、この記事で紹介したすべての内容を体験できます。ぜひ試してみてください。