Skip to content
This page has been auto-translated and may contain errors.View in English

出力と入力

最初のコード行から使う2つのツール:print() はターミナルに値を表示し、input() はユーザーからテキストを取得します。シンプルですが、その挙動を知っておくことで、初期に遭遇するちょっとした驚きを避けられます。

print()input() は Python の標準的なターミナル I/O 関数です。両方とも一見よりも設定可能です。print() は値の結合方法と出力の終わり方を制御する引数を受け付けます。input() は常に文字列を返し、これがユーザーから来るすべての値の扱い方を決定づけます。

print()sys.stdout をラップし、input()sys.stdin をラップします。両方ともテキストのみを扱い、エンコーディングはストリームのコーデックに委ね、デフォルトでは出力をバッファリングします。stdout と stderr の分離、そしてフラッシングの制御は、実際のプログラムで重要になります。

Python がコードを実行する仕組み

Python はコードを上から下へ、一行ずつ、書いた順番どおりに実行します。ジャンプはしません。書いた順がそのまま実行順です。常に。

python
city = "東京"
print(city)
print("人口: 1400万人")

city が最初に代入されます。最初の print が実行されます。次の print が実行されます。毎回、その順序で。

これが重要なのは、変数を代入する前に使うことができないからです。Python はまだそれを見ていないので、エラーを発生させます:

python
print(country)   # NameError: country はまだ定義されていない
country = "日本"

プログラムが大きくなっても、これを覚えておいてください:使うものは、使う前に定義されていなければなりません。

Python は逐次実行を使用します:各文は、ファイルを上から下へ1パスで進む中で、出会った順に評価されます。ファイル全体を事前にスキャンすることはありません。代入される前の名前を参照すると、まさにその行で NameError が発生します。それより前ではありません。

python
city = "東京"
print(city)             # 動作する: city はすでにバインドされている
print(country)          # NameError: まだ代入されていない
country = "日本"

ルールは単純です:依存するものは、それを使う行の前に定義されている必要があります。

Python の実行モデルは、シングルパスの逐次評価です。名前解決は、解析時ではなく評価時点で行われます。パーサーは名前を解決せずにバイトコードを構築します。これが、NameError が構文エラーではなくランタイム例外である理由です。Python には巻き上げ(JavaScript の var と異なり)も前方宣言(C と異なり)もありません。名前はバインドされた瞬間から利用可能になります。それまでは、どんな参照もエラーを発生させます。

python
print(country)   # 構文エラーではなく、ランタイムでの NameError
country = "日本"

出力の表示

print() は Python があなたに話しかける方法です。任意の値を渡すと、その値を表示します。渡したものを自動的にテキストに変換します。

print() は各引数を str() で文字列に変換し、セパレーター(デフォルトは空白)で結合してから、結果を改行付きで標準出力に書き込みます。デフォルトを理解すると、オプション引数も推測しやすくなります。

print() の完全なシグネチャは print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) です。*objects コレクターは任意の数の位置引数を受け取り、それぞれに対して str() を呼び出します。sepend は書式を制御し、file は出力を任意の書き込み可能なストリームへリダイレクトし、flush はバッファを即座に流すよう強制します。

python
print("Hello")    # Hello
print(42)         # 42
print(3.14)       # 3.14
print(True)       # True

複数の値

カンマで区切ることで、複数の値を一度に表示できます。Python はデフォルトでそれらの間にスペースを挿入します。sep でセパレーターを変更できます:

複数の位置引数はそれぞれ個別に str() で変換され、その後 sep で結合されます。デフォルトの sep は1つのスペースです。これを上書きすることで、文字列連結なしに書式化された出力を作れます:

各位置引数は、結合する前に個別に str() を通されます。結合は sep を使い、その後 end が追加され、全体が1回の呼び出しで出力ストリームに書き込まれます。sep を上書きする方が、手動で文字列を構築するよりきれいです:

python
name = "さくら"
age  = 28
print(name, age)                        # さくら 28
print("名前:", name)                    # 名前: さくら
print("2024", "01", "15", sep="-")     # 2024-01-15
print("a", "b", "c", sep=", ")         # a, b, c

行末の制御

print() 呼び出しはデフォルトで改行で終わるので、次の出力は新しい行から始まります。end でそれを変更できます。end="" を設定すると、次の print は同じ行に続きます:

end パラメーターはデフォルトの改行を置き換えます。"" に設定すると改行を抑制し、" " でスペース付きで同じ行に留まり、その他任意の文字列を設定できます。sep と組み合わせれば、手動で文字列を構築せずに、ほとんどの出力形式を作れます:

sepend はキーワード専用の引数で、デフォルトはそれぞれ ' ''\n' です。end="" を設定するのは、部分的な行を出力して次の呼び出しでそれを続けるための標準的な方法です。プログレスインジケーターやログのようなリアルタイム出力には、flush=True を使ってバッファを即座に流し、改行やバッファ充填を待たないようにします。

python
print("Loading", end="")
print("...")
# Loading...

print("one", end=" | ")
print("two", end=" | ")
print("three")
# one | two | three

f-string による出力の書式化

メッセージを組み立てる最もきれいな方法は f-string です。開始引用符の前に f を付け、変数や式を中括弧で囲みます。Python が実行時に埋め込んでくれます。{} の中には、任意の値、計算、メソッド呼び出しを入れられます。

f-string は {} の中の任意の式を実行時に評価し、結果を文字列として埋め込みます。値の後のコロンはフォーマット仕様を導入します:小数点以下の桁数、配置、数値の書式を制御するコンパクトな構文です。連結よりも高速で読みやすく、明示的な str() 呼び出しも必要ありません。

f-string(PEP 498)は各 {} を、format(value, spec) を呼び出すバイトコードにコンパイルし、それが value.__format__(spec) に委譲します。__format__ を実装するクラスは、f-string 内での自身の表示を制御します。変換フラグ !r!s!a はフォーマット呼び出しの前にそれぞれ repr()str()ascii() を適用します。!r が最も有用です:文字列を引用符で囲んで表示し、不可視文字を見えるようにします。

python
name  = "さくら"
score = 980

# 連結: 不格好、数値には str() が必要
print("Player: " + name + ", Score: " + str(score))

# f-string: 読みやすく、手動変換が不要
print(f"Player: {name}, Score: {score}")

{} の中には任意の式を入れられます:算術、メソッド呼び出し、フォーマット仕様:

python
price = 49.99
tax   = 0.2
total = price * (1 + tax)

print(f"合計: {total:.2f}")          # 合計: 59.99
print(f"名前: {name.upper()}")        # 名前: さくら
print(f"2 + 2 = {2 + 2}")             # 2 + 2 = 4

: の後のフォーマット仕様は、値の表示方法を制御します:

python
ratio = 0.8765
count = 1234567
label = "revenue"

print(f"{ratio:.1%}")       # 87.7%
print(f"{count:,}")         # 1,234,567
print(f"{label:>12}")       # "     revenue"

:.2f は「小数点以下2桁」を意味します。価格や測定値で頻繁に使うことになります。それ以外は必要なときに使えばよいだけです。重要なのは、{} の中には変数名だけでなく、何でも入れられるということです。

:.2f:.0% はほとんどの書式化のニーズをカバーします。配置指定子(><^)と幅を組み合わせると、整然とした表形式の出力ができます。一般的なパターンは {value:[align][width][.precision][type]} です。各部分を認識できれば、すべての組み合わせを暗記しなくても任意の仕様を読めるようになります。

仕様文字列はそのまま value.__format__(spec) に渡されます。組み込み型は C 言語でフォーマットミニ言語を実装しています。カスタムクラスは __format__ を定義して任意の仕様文字列を受け付けることができます。!r はフォーマットの前に repr() を呼び出します:f"{name!r}" は末尾に空白がある文字列を引用符付きの repr に変え、不可視文字を見えるようにします。変数の値がおかしく見えて、中に何が入っているかを正確に知りたいときに使いましょう。

ユーザーからの入力の取得

input() はプログラムを一時停止し、ユーザーが何かを入力するのを待ちます。ユーザーが入力(して Enter キーを押す)した内容が戻り値として返ります。括弧内の文字列は、ユーザーに表示されるプロンプトです。

python
name = input("お名前は? ")
print(f"こんにちは、{name}さん!")

input() は、ユーザーが何を入力しても、常に文字列を返します。42 と入力しても、数値の 42 ではなく "42" が返ってきます。算術演算をするには、明示的に変換します:

python
age = int(input("年齢は? "))
print(f"10年後にはあなたは {age + 10} 歳になります。")

変換できないものを入力するとどうなるでしょうか? Python は ValueError を発生させます。これを適切に扱う方法は ファイルと例外 の章で扱います。

input() はプロンプトを標準出力に書き込み、標準入力から1行読み取り、末尾の改行を取り除き、結果を文字列として返します。型推論はありません。ターミナルから来るものすべてはテキストとして到着します。必要な型は、境界で明示的に変換することで宣言します。

python
name = input("お名前は? ")
age  = int(input("年齢は? "))

このパターン(テキストを受け取り、必要な型に変換する)は、外部データが入ってくるあらゆる場所に適用されます。int()float()str() が変換のためのツールです。文字列を変換できない場合、Python は ValueError を発生させます。これは ファイルと例外 の章で扱います。

input() は薄いインターフェースです:sys.stdout.write(prompt) を呼び出し、stdout をフラッシュし、sys.stdin から1行を読み取り、末尾の改行を取り除いて、結果を str として返します。戻り値が常に str であるのは設計によるものです:Python には "42" が整数、浮動小数点数、リテラル文字のいずれとして意図されたかを推論する手段がありません。境界での型変換は明示的です。これは Python の I/O における基本的なパターンです:すべての外部データはテキストとして到着し、コードはエントリポイントで型を宣言します。

python
name  = input("名前を入力してください: ")
score = float(input("スコアを入力してください (0.0 から 1.0): "))

print(f"Name:  {name!r}")      # !r は不可視の空白を明らかにする
print(f"Score: {score:.1%}")

stderr への書き込み

デフォルトでは、print()標準出力に書き込みます:ターミナルに表示され、パイプに流れるストリームです。Python には標準エラーもあり、これは診断や警告のための別個のストリームです。ターミナルでは同じに見えますが区別されています:スクリプトの出力を別のコマンドにパイプすると、stdout のみが通過します。stderr は常にターミナルに到達します。

stderr への書き込みには print()file 引数を使います。これには sys のインポートが必要で、これは モジュール の章で扱います。今は、2つのストリームが存在することと、なぜそれらが分離されているのかを知っておけば十分です。

実践

ユーザー入力からパーソナライズするクイズ:

python
name    = input("お名前は? ")
subject = input("どの科目? ")

print(f"わかりました、{name}さん。{subject} クイズを開始します。")
print("頑張ってください!")

どちらの入力も文字列として返ってきて、そのまま f-string に入ります。数値ではなくテキストとして使っているので、変換は不要です。

整列された表形式出力を持つ温度変換器:

python
celsius    = float(input("摂氏温度: "))
fahrenheit = celsius * 9 / 5 + 32

print(f"{'Celsius':>12} {'Fahrenheit':>12}")
print(f"{celsius:>12.1f} {fahrenheit:>12.1f}")

float() はユーザーからの整数と小数の両方を処理します。>12 指定は、数字の桁数に関係なく列の整列を保ちます。100-40 を入力してみてください:出力はどちらでもきれいに保たれます。

!r を使って Python が実際に受け取ったものを正確に表面化させる。出力がおかしく見えるときに有用です:

python
name  = input("名前を入力してください: ")
score = float(input("スコアを入力してください (0.0 から 1.0): "))

print(f"Name:   {name!r}")
print(f"Score:  {score!r}")
print()
print(f"Result: {name}: {score:.1%}")

入力がきれいなとき、{name}{name!r} は同じように表示されます。末尾の空白やその他の不可視文字があるときに違いが現れます。デバッグ中に !r を使う習慣をつけることで、予期しない値がすぐに見えるようになります。

Python で出力と入力を練習するScrimba コースで、print、f-string、ユーザー入力の実践的な演習に取り組みましょう。Start the course →