キーボードから値を受け取り、プログラムを対話的に動かすにはinput()
が基本です。
本記事では、input()
の仕様から文字列・数値の扱い、複数値や再入力ループ、実用サンプル、つまずきやすいポイントまでを丁寧に解説します。
現場で役立つ型変換と検証のパターンも例付きで整理します。
input()とは?Pythonの基本の使い方と仕様
input()
は標準入力から1行を読み取り、文字列として返す関数です。
プロンプト表示、エラー処理、末尾改行の扱いなど、基本の振る舞いを正しく理解しておくと、その後の実装がスムーズになります。
input()の戻り値は常にstr(文字列)
input()
の戻り値は、ユーザーがEnterを押して確定した1行の「文字列」です。
数値に見えても、そのままでは文字列のため、数値計算をしたい場合はint()
やfloat()
で明示的に型変換します。
デモ:戻り値の型を確認する
# ユーザーに年齢を尋ねて型を確認する
age_text = input("年齢を入力してください: ")
print(age_text, type(age_text)) # <class 'str'> と表示される
年齢を入力してください: 25
25 <class 'str'>
プロンプトの表示方法とユーザー体験
input(prompt)
に文字列を渡すと、その文字列が入力前に表示されます。
わかりやすいプロンプトはエラーを減らします。
例として、期待する形式や例を示すと親切です。
# 期待する形式を明記し、例を添える
email = input("メールアドレス(例: user@example.com)を入力してください: ")
print(f"入力されたメール: {email}")
プロンプト設計のコツ
- 何を、どの形式で入力すべきかを短く明示します。
- 必須・任意や、デフォルト値の有無を知らせます。
- 可能なら例を示します(「例: 2025-08-17」など)。
末尾改行の扱いとstripの必要性
input()
はユーザーのEnterによる末尾改行を含めずに返します。
したがって「改行の除去」のためにstrip()
は不要です。
ただし前後の空白、全角スペースの除去、不要な制御文字の整理にはstrip()
や正規化が有効です。
# 改行は含まれないが、前後空白は残るため必要に応じてstripする
raw = input("名前(前後空白は無視します): ")
name = raw.strip() # " 太郎 " -> "太郎"
print(f"こんにちは、{name}さん")
補足として、sys.stdin.readline()
は末尾に改行(’\n’)を含む点がinput()
と異なります(後述)。
文字列入力の実践:空入力・正規化・検証
文字列入力では、空入力の扱い、表記のゆれ(大文字/小文字)、前後空白や全角スペースへの対処がポイントです。
空文字の検知とデフォルト値の設定
ユーザーが何も入力せずEnterを押したときの扱いを決めておくと使いやすくなります。
# 空入力なら「ゲスト」を採用する
def ask_nickname(default="ゲスト"):
text = input(f"ニックネーム(未入力で'{default}'): ").strip()
return text if text else default
nick = ask_nickname()
print(f"こんにちは、{nick}さん!")
ニックネーム(未入力で'ゲスト'):
こんにちは、ゲストさん!
大文字小文字の正規化(lower/upper)
コマンドやオプションの入力は、大文字小文字の差をなくすと便利です。
# y/n の確認で大文字小文字を無視する
ans = input("上書きしますか? [y/N]: ").strip().lower()
if ans in ("y", "yes"):
print("上書きします。")
else:
print("キャンセルしました。")
上書きしますか? [y/N]: YES
上書きします。
前後空白の除去(strip)と全角・半角の扱い
日本語入力では全角スペースや全角記号が混ざることがあります。
strip()
に全角スペースを明示する、あるいはunicodedata.normalize
で正規化してから処理すると堅牢です。
import unicodedata
def normalize_text(s: str) -> str:
# 全角→半角も含む正規化(NFKC)を行い、前後の空白(半角・全角)を削除
s = unicodedata.normalize("NFKC", s)
return s.strip(" \t\u3000")
raw = input("郵便番号(ハイフン可。例: 123-4567): ")
text = normalize_text(raw)
print(f"正規化後: '{text}'")
郵便番号(ハイフン可。例: 123-4567): 123−4567
正規化後: '123-4567'
数値入力の基本:int()・float()での型変換とエラー対処
数値として扱うには、文字列から数値への安全な変換と、エラー時の扱い(再入力など)が重要です。
int()・float()で文字列を数値に変換
単純なケースは直接変換できますが、失敗時にValueError
が発生します。
# 身長と体重からBMIを計算
try:
h = float(input("身長(cm): ")) / 100.0
w = float(input("体重(kg): "))
bmi = w / (h * h)
print(f"BMI: {bmi:.1f}")
except ValueError:
print("数値を正しく入力してください。")
身長(cm): 170
体重(kg): 65
BMI: 22.5
isdigit()の限界とtry/exceptでのバリデーション
str.isdigit()
は「数字のみ」を対象とし、負号・小数点・全角数字・空白などを扱えません。
複雑な入力を許容するなら、最終的にはtry/except
での変換確認が堅実です。
samples = ["123", "-5", "3.14", "123", "1 000"]
for s in samples:
print(s, s.isdigit())
123 True
-5 False
3.14 False
123 False
1 000 False
再入力ループの設計(エラーメッセージとガイド)
ユーザーが誤入力しやすい箇所は、ガイド付きで再入力させます。
範囲チェックも合わせて行うと親切です。
# 0〜120の年齢を整数で受け取る再入力ループ
def ask_age(min_age=0, max_age=120):
prompt = f"年齢({min_age}〜{max_age}の整数): "
while True:
try:
age = int(input(prompt))
except ValueError:
print("整数で入力してください。例: 34")
continue
if not (min_age <= age <= max_age):
print(f"{min_age}〜{max_age}の範囲で入力してください。")
continue
return age
age = ask_age()
print(f"登録年齢: {age}")
年齢(0〜120の整数): 三十
整数で入力してください。例: 34
年齢(0〜120の整数): 150
0〜120の範囲で入力してください。
年齢(0〜120の整数): 30
登録年齢: 30
複数値の受け取り:split()・map()・リスト活用
1行に複数の値を入力させると、コマンドラインツールの操作性が上がります。
1行で複数値を取得する(splitとmapの組み合わせ)
スペース区切りで2つの整数を受け取る例です。
# 2つの整数をスペース区切りで入力させる
a, b = map(int, input("2つの整数をスペース区切りで入力: ").split())
print(f"a+b={a+b}, a*b={a*b}")
2つの整数をスペース区切りで入力: 10 20
a+b=30, a*b=200
カンマ・タブ区切りの入力に対応する
複数の区切り文字を許容するにはre.split
が便利です。
import re
line = input("数値をカンマ/スペース/タブ区切りで入力(例: 1, 2\t3): ")
parts = [p for p in re.split(r"[,\s]+", line.strip()) if p] # 連続区切りもケア
nums = list(map(float, parts))
print(f"合計={sum(nums)}, 個数={len(nums)}")
数値をカンマ/スペース/タブ区切りで入力(例: 1, 2 3): 1, 2 3 4.5
合計=10.5, 個数=4
複数行の入力をfor/whileで読む
N行のデータや、空行で終了する可変行を読み取る方法です。
# Nを先に受け取り、続くN行を読む
n = int(input("行数N: "))
lines = []
for i in range(n):
lines.append(input(f"{i+1}行目: ").rstrip()) # 念のため末尾空白を除去
print("入力行:", lines)
# 空行で終了するパターン
print("空行だけで終了。複数行入力開始:")
rows = []
while True:
s = input()
if s == "":
break
rows.append(s)
print("受け取った行数:", len(rows))
行数N: 3
1行目: apple
2行目: banana
3行目: cherry
入力行: ['apple', 'banana', 'cherry']
空行だけで終了。複数行入力開始:
red
green
blue
受け取った行数: 3
例付きパターン集:input()の実用サンプル
よく使う入力パターンを、まとめてコード化します。
メニュー選択と数値検証のサンプル
def ask_menu_choice():
menu = {
1: "新規作成",
2: "開く",
3: "保存",
0: "終了"
}
while True:
print("=== メニュー ===")
for k, v in menu.items():
print(f"{k}: {v}")
try:
choice = int(input("番号を入力してください: "))
except ValueError:
print("数字で入力してください。")
continue
if choice in menu:
return choice
print("存在しない番号です。もう一度。")
choice = ask_menu_choice()
print(f"選択: {choice}")
=== メニュー ===
1: 新規作成
2: 開く
3: 保存
0: 終了
番号を入力してください: a
数字で入力してください。
=== メニュー ===
1: 新規作成
2: 開く
3: 保存
0: 終了
番号を入力してください: 3
選択: 3
合計・平均を計算する数値入力のサンプル
import re
def ask_numbers():
line = input("数値をスペース/カンマ区切りで入力(例: 10, 20 30): ")
parts = [p for p in re.split(r"[,\s]+", line.strip()) if p]
nums = []
for p in parts:
try:
nums.append(float(p))
except ValueError:
print(f"数値ではありません: {p!r}")
return None
return nums
nums = ask_numbers()
if nums:
total = sum(nums)
avg = total / len(nums)
print(f"合計={total}, 平均={avg}")
数値をスペース/カンマ区切りで入力(例: 10, 20 30): 10, 20 30
合計=60.0, 平均=20.0
日付(年・月・日)を3つの入力で受け取るサンプル
datetime.date
で妥当性を検証できます。
import datetime
def ask_date():
while True:
try:
y = int(input("年(YYYY): "))
m = int(input("月(MM): "))
d = int(input("日(DD): "))
date = datetime.date(y, m, d)
return date
except ValueError as e:
print(f"無効な日付です。もう一度(例: 2025 / 08 / 17)。詳細: {e}")
dt = ask_date()
print("受け取った日付:", dt.isoformat())
年(YYYY): 2024
月(MM): 2
日(DD): 29
無効な日付です。もう一度(例: 2025 / 08 / 17)。詳細: day is out of range for month
年(YYYY): 2024
月(MM): 2
日(DD): 28
受け取った日付: 2024-02-28
つまずきポイントとベストプラクティス
実運用では、標準入力がない環境、速度要件、エンコーディング、テスト容易性など、周辺事情の理解が重要です。
EOFErrorの原因と対処(オンラインジャッジ・リダイレクト)
input()
は入力が尽きるとEOFError
を送出します。
オンラインジャッジやファイルからのリダイレクト時に起きがちです。
例外を捕捉して終了処理やデフォルト値に切り替えます。
# EOFに達したら静かに終了する
try:
s = input()
except EOFError:
s = None
if s is None:
print("入力がありませんでした。終了します。")
else:
print("受信:", s)
入力がありませんでした。終了します。
連続読み取りではwhile True
内で都度捕捉するか、for line in sys.stdin
のスタイルを使うと楽です(後述)。
sys.stdin.readline()との違いと高速入力のコツ
大量データの読み取りではsys.stdin.readline()
が高速です。
主な違いは次の通りです。
項目 | input() | sys.stdin.readline() |
---|---|---|
戻り値 | 末尾改行なしのstr | 末尾に改行を含むstr(空行は”\n”) |
例外 | EOFでEOFError | EOFで空文字””を返す |
速度 | 手軽、やや遅い | 速い(ループ・大量入力向け) |
import sys
# 高速に複数行を読む例(改行をrstripで除去)
lines = []
for _ in range(3):
line = sys.stdin.readline()
if line == "": # EOF
break
lines.append(line.rstrip("\n"))
print(lines)
['foo', 'bar', 'baz']
オンラインジャッジなどでは、sys.stdin.readline()
やsys.stdin.read().split()
を活用し、必要に応じてPyPy
の使用やpypy + sys.stdin
系テクニックで速度を確保します。
日本語・全角数字の取り扱いとエンコーディング
- 全角数字や記号は
unicodedata.normalize("NFKC", s)
で半角に正規化してから数値変換するのが安全です。 - Windowsコンソールやリダイレクトでは文字化けの可能性があります。Python 3.11以降はUTF-8モードが改善されていますが、必要に応じて次のように明示できます。
import sys
# 標準入力のエンコーディングをUTF-8に再設定(環境依存。必要時のみ)
try:
sys.stdin.reconfigure(encoding="utf-8")
sys.stdout.reconfigure(encoding="utf-8")
except AttributeError:
pass # 古いPythonでは未対応
また、ファイルから読み込む場合はopen(path, encoding="utf-8")
を指定してください。
入力ロジックの関数化とテスト(モック・依存性分離)
入力と検証を関数化すると再利用とテストが容易です。
unittest.mock
でinput
を差し替えれば対話なしでテストできます。
# 入力+検証を関数に閉じ込める
def ask_int_in_range(prompt: str, lo: int, hi: int) -> int:
while True:
try:
v = int(input(prompt))
except ValueError:
print("整数で入力してください。")
continue
if lo <= v <= hi:
return v
print(f"{lo}〜{hi}の範囲で入力してください。")
if __name__ == "__main__":
x = ask_int_in_range("点数(0-100): ", 0, 100)
print("受理:", x)
簡単なテスト例です。
# テスト例(unittest + mock)
import unittest
from unittest.mock import patch
class TestInput(unittest.TestCase):
def test_ask_int_in_range(self):
# 文字→範囲外→妥当 という入力を順に供給
inputs = iter(["abc", "120", "85"])
with patch("builtins.input", lambda _: next(inputs)):
with patch("builtins.print"): # ノイズ抑制
self.assertEqual(ask_int_in_range("点数(0-100): ", 0, 100), 85)
if __name__ == "__main__":
unittest.main()
.
----------------------------------------------------------------------
Ran 1 test in 0.00s
OK
まとめ
input()
は戻り値が常に文字列である点を起点に、プロンプト設計、空入力・大小文字・空白や全角の正規化、int()
/float()
による型変換、try/except
での堅牢な検証へとつながります。
複数値の取得にはsplit()
やmap()
、大量入力にはsys.stdin.readline()
が有効です。
日本語や全角数字はunicodedata.normalize
で正規化し、エンコーディングにも配慮すると安心です。
最後に、入力ロジックは関数化してテスト可能にすることで、保守性と品質を高められます。
日々の小さな入力処理でも、これらのベストプラクティスを取り入れて使い勝手と信頼性を両立させてください。