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

出力と入力

docs.scrimba.com

最初の1行から使用する2つのツール: print()はターミナルに値を表示し、input()はユーザーからテキストを取得します。シンプルですが、その動作方法を理解することで初期段階での予期しない問題を回避できます。

print()input()はPythonの標準的なターミナルI/O関数です。どちらも最初の印象よりも設定可能です。print()は値の結合方法と出力の終わり方を制御する引数を受け入れます。input()は常に文字列を返すため、ユーザーから来たあらゆる値の処理方法に影響します。

内部的には、print()sys.stdoutに書き込み、input()sys.stdinから読み込みます(ターミナルが接続されている標準出力と標準入力ストリーム)。両者はテキストのみを処理し、出力はデフォルトでバッファリングされます。Pythonは一度に1文字ずつではなく、チャンク単位で保持して書き込みます。実際のプログラムでは2つの結果が重要です。出力はエラーとは異なるストリームに送られ(stdoutとstderr)、必要に応じてそのバッファをフラッシュして出力を即座に表示させることができます。

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

Pythonはコードを上から下へ、1行ずつ、書いた順序そのままに実行します。ジャンプすることはありません。物事を書いた順序が実行される順序です。常にそうです。

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

cityはまず割り当てられます。最初のprintが実行されます。2番目のprintが実行されます。毎回、その順序です。

これが重要な理由は、変数を割り当てる前に使用できないからです。Pythonはまだそれを見ていないため、エラーが発生します:

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

プログラムが成長するにつれ、これを念頭に置いてください: 使用するすべてのものは、使用する前に定義する必要があります。

Pythonは**順序実行**を使用します: 各ステートメントはそれが遭遇した時点で評価され、ファイルを通る単一の上から下への1パスで実行されます。最初にファイル全体をスキャンすることはありません。割り当てられる前に名前を参照すると、その行で正確にNameErrorが発生します。それより前ではありません。

python
city = "東京"
print(city)             # 機能する: cityは既に結合されている
print(country)          # NameError: まだ割り当てられていない
country = "日本"

ルール: 依存関係は使用する行の前に定義する必要があります。

Pythonはファイルを単一の上から下への1パスで実行し、ファイルを最初に読むときではなく、その行が実際に実行される瞬間に限定名を検索します。これが欠落している名前が、ファイルを保存した瞬間ではなく、実行時(行が実行された時)にNameErrorである理由です。ホイスティング(JavaScriptがvar宣言をそのスコープの上部に静かに移動する方法)と前方宣言(Cで今名前を約束して後で定義することができる方法)はありません。名前は割り当てられた瞬間に存在し、それより前のあらゆる使用は発生します。

python
print(country)   # 構文エラーではなく実行時エラー
country = "日本"
JunoPythonがコードを実行する仕組み Pythonはファイルを上から下へ、1行ずつ、書いた順序で読みます。みんなを一度は引っかかせる落とし穴: 名前はそれを使用する行の前に存在する必要があります。さもなければNameErrorが発生します。先へ飛ぶことはできません。ファイル全体を最初に読むこともありません。
JunoPythonがコードを実行する仕組み 上から下へ、1パス、順序で実行します。名前は使用するあらゆる行の前に割り当てる必要があります。さもなければその行でNameErrorです。ファイルの事前スキャンはありません。
JunoPythonがコードを実行する仕組み 上から下への1パス、各行が実行されるときに検索された名前。割り当てられる前に名前を使用すると、構文エラーではなく実行時にNameErrorが発生します。Pythonはホイストせず、前方宣言がないため、順序が本当に重要です。

出力を印字する

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は単一のスペースです。それをオーバーライドすると、文字列連結なしでフォーマットされた出力を生成できます:

print()は1つの文字列をビルドして書き込むのではなく、各引数をストリームに順番に書き込み(各引数にstr()を呼び出す)、sepを間に置いてendで終わります。これらの書き込みは単一のロック操作としてではなく1つずつ発生するため、同時に実行される(異なるスレッド上の)2つのprint()呼び出しは出力をインターリーブできます。それが重要な場合は、1つの文字列をビルドして1回印字してください。日常的な使用では、sepをオーバーライドすることは依然として文字列を手作業で接着するよりも優れています:

python
name = "太郎"
age = 28
print(name, age)                        # 太郎 28
print("Name:", name)                    # Name: 太郎
print("2024", "01", "15", sep="-")     # 2024-01-15
print("a", "b", "c", sep=", ")         # a, b, c

行の終わり方を制御する

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

endパラメータはデフォルトの改行を置き換えます。""に設定して改行を抑制するか、" "に設定して同じ行にスペースで留まるか、または他の文字列に設定します。sepと組み合わせると、ほとんどの出力フォーマットを手作業で文字列をビルドせずに生成できます:

sependはキーワードのみです(end=""のように名前で渡します。決して位置では渡しません)。デフォルトはスペースと改行です。end=""は部分的な行を印字し、次の呼び出しがそれを続けさせる標準的な方法です。進捗インジケータやライブログのように出力が発生するときに表示される必要があるには、flush=Trueを追加して、改行またはバッファがいっぱいになるのを待つのではなく、Pythonが即座に書き込むようにします。

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

print("one", end=" | ")
print("two", end=" | ")
print("three")
# one | two | three
Juno出力を印字するprint()は与えたものをテキストに変換して表示します。コンマで区切って複数のものを渡すと、それらの間にスペースが表示されます。sepでそれを変更します。すべての印字は最後に新しい行にドロップされます。end=""は次のものを同じ行に保ちます。
Juno出力を印字するprint()は各引数に対してstr()を実行し、sep(デフォルトはスペース)で結合し、end(デフォルトは改行)で終わります。フォーマットされた出力を文字列で接着することなく、どちらかをオーバーライドします。
Juno出力を印字するprint()は各引数をstr()経由で書き込み、sepを間に置いてendで終わります。どちらもキーワードのみです。行を続けるにはend=""に手を伸ばし、出力が即座に表示される必要があるときはflush=Trueを使用します。

f-stringsで出力をフォーマットする

メッセージを構築する最もクリーンな方法はf-stringsです。開き引用符の前にfを置き、変数または式を波括弧で囲みます。Pythonは実行時にそれを埋めます。{}内には任意の値、計算、またはメソッド呼び出しを入れることができます。

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

f-stringの各{}は結局format(value, spec)を呼び出し、その値独自の__format__メソッド(dunder、値をフォーマットするためにPythonが呼び出す二重下線メソッド)に手を渡します。したがって、あらゆるクラスは__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}")

{}内には任意の式を入れることができます: 算術、メソッド呼び出し(.upper()など、Stringsの章で完全に説明)、フォーマット仕様:

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

print(f"Total: {total:.2f}")          # Total: 59.99
print(f"Name: {name.upper()}")        # Name: 太郎
print(f"2 + 2 = {2 + 2}")             # 2 + 2 = 4

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

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

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

:.2fは「小数点以下2桁」を意味します。価格と測定用に絶えず使用します。その他すべてはそれが必要なときにそこにあります。主なこと: 変数名だけではなく、あらゆるものが{}内に入ることができます。

:.2f:.0%はほとんどのフォーマットニーズをカバーしています。配置指定子(><^)と幅はきれいな表形式の出力を生成します。一般的なパターンは{value:[align][width][.precision][type]}です。パーツを認識すると、すべての組み合わせを暗記することなく、あらゆる仕様が読めます。

異なる型は異なることを意味することができます。なぜなら各型は独自の形式だからです。f"{'hi':5}"はテキストを右側にパッドします(テキストはデフォルトで左寄せ)一方、f"{42:5}"は左側にパッドします(数値は右寄せ): 同じ:5、反対の結果。各組み込み型はこのフォーマット小言語に対して独自の規則を持ち、カスタムクラスは__format__を定義することで独自の規則を設定します。

Junof-stringsで出力をフォーマットする 開き引用符の前にfを置き、あらゆるものを{}で囲みます: 変数、合計、メソッド呼び出しさえも。コロンはフォーマットを追加します。例えば小数点以下2桁の場合は:.2fです。`+`で文字列を接着するよりもはるかにクリーンです。
Junof-stringsで出力をフォーマットするf"..."str()が不要な場合、あらゆる式の結果を文字列に直接ドロップします。コロンの後にはフォーマット仕様が続きます: :.2f:,:>12など。連結より洗練されており、高速です。
Junof-stringsで出力をフォーマットする{}は値独自の__format__を呼び出すため、コロンの後の仕様はその型が決定するものを意味します。覚えておく方法は!rです: 値をコードで入力する方法を示しており、スタイル出力をデバッグするときに予期しない値が見えやすくなります。

ユーザーから入力を取得する

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

python
name = input("あなたの名前は? ")
print(f"こんにちは、{name}!")

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

python
age = int(input("あなたは何歳ですか? "))
print(f"10年後には{age + 10}歳になっているでしょう。")

ユーザーが変換できないものを入力した場合、PythonはValueErrorを発生させます。これを適切に処理することはFiles and exceptionsの章で説明されています。

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

python
name = input("あなたの名前は? ")
age = int(input("あなたは何歳ですか? "))

このパターン(テキストを受け取り、必要な型に変換)は外部データが到着するあらゆる場所に適用されます。int()float()str()は変換ツールです。文字列を変換できない場合、PythonはValueErrorを発生させます。Files and exceptionsの章で説明されています。

input()は薄いラッパーです: プロンプトをsys.stdout(標準出力)に書き込み、プログラムがブロックされる前にプロンプトが表示されるようにフラッシュし、sys.stdin(標準入力)から1行を読み込み、末尾の改行を削除して、strを返します。設計上、常にstrです。Pythonは"42"が整数、浮動小数点数、またはリテラルテキストを意図したのかを推測できないため。したがって、境界で変換します。これはPython I/Oの基本的な形です: 外部データはテキストとして到着し、コードはエントリーポイントでその型を決定します。

python
name = input("あなたの名前を入力してください: ")
score = float(input("スコアを入力してください(0.0~1.0): "))

print(f"名前:  {name!r}")      # !rは見えない空白を明らかにする
print(f"スコア: {score:.1%}")
Junoユーザーから入力を取得するinput()はプロンプトを表示し、行を待機して、常にstringとして返します。数字を入力した場合でも。数値が必要ですか? 入力時にint()またはfloat()で自分で変換してから、正しい型で続行します。
Junoユーザーから入力を取得するinput()は常にstrを返します。型推論なし。`int()`または`float()`で境界で変換し、テキストが解析されない場合は`ValueError`を予期してください。そのreceive-then-convertパターンは外部データが存在するあらゆる場所で表示されます。
Junoユーザーから入力を取得するinput()からのすべてが設計上strです。Pythonは何を意図したのかを推測できないため。エントリーポイントで変換し、解析されない場合は`ValueError`を処理してください。外部データが到着する他のあらゆる場所と同じ形です。

stderrに書き込む

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

stderrへの書き込みはprint()file引数を使用します。これにはsysのインポートが必要です。これはModulesの章で説明されています。今のところ、2つのストリームが存在し、なぜ分離されているのかを知ることで十分です。

実践に

ユーザー入力から自分をカスタマイズするクイズ:

python
name = input("あなたの名前は? ")
subject = input("どの科目ですか? ")

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

両方の入力は文字列として返され、f-stringsに直接送られます。テキストではなく数値として使用しているため、変換は不要です。

配置された表形式の出力を持つ温度コンバーター:

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

print(f"{'摂氏':>12} {'華氏':>12}")
print(f"{celsius:>12.1f} {fahrenheit:>12.1f}")

float()はユーザーからの整数と小数の両方を処理します。:>12仕様は、数値が何桁あるかに関わらず、列を配置しておきます。100-40を入力してみてください: 出力はどちらの方法でもきれいに保たれます。

Pythonが正確に受け取ったものを表示するために!rを使用します。出力が間違っているように見える場合に有用です:

python
name = input("あなたの名前を入力してください: ")
score = float(input("スコアを入力してください(0.0~1.0): "))

print(f"名前:   {name!r}")
print(f"スコア:  {score!r}")
print()
print(f"結果: {name}: {score:.1%}")

入力がきれいな場合、{name}{name!r}は同じように表示されます。末尾のスペースまたは他の見えない文字がある場合、違いが表示されます。デバッグ中に!rの習慣を身に付けると、予期しない値が即座に見えるようになります。