Pythonを学びはじめて、最初に書いたコードを覚えていますか。多くの人にとって、それはprint()でHello, Worldを表示する1行だったはずです。
あまりに身近な関数なので、改めて使い方を調べる機会は少ないかもしれません。けれどもprint()には、文字を表示するだけではない便利な引数がいくつも用意されています。
今回は、print()が持つsep・end・file・flushの4つの引数を中心に、知っていると少し得をする使い方を紹介します。サンプルコードの結果は、手元のPython 3.11で実際に動かして確かめたものです。
毎日のように使う関数だからこそ、ちょっとした知識の差がコードの読みやすさに表れます。一緒に見ていきましょう。
print()の基本をおさらいしよう¶
まずは、いちばん基本の動きから確認しておきます。print()は、渡した値を画面に表示する組み込み関数です。importをしなくても、いつでも使えます。
値はカンマで区切って、いくつでも渡せます。数値や文字列が混ざっていても、そのまま表示してくれます。
print("りんご", "みかん", "ぶどう")
print("名前:", "佐藤", 28, "歳")
実行すると、次のように表示されます。
りんご みかん ぶどう
名前: 佐藤 28 歳
値と値のあいだに、自動で半角スペースが入っていますね。そして行の終わりでは、自動で改行されています。
この2つの自動の動きを決めているのが、このあと紹介するsepとendです。
公式ドキュメントに書かれた形¶
Pythonの公式ドキュメントでは、print()は次のような形で説明されています。引数の並びを見ると、隠れた機能が見えてきます。
print(*objects, sep=' ', end='\n', file=None, flush=False)
最初のobjectsは、表示したい値をいくつでも受け取れるという意味です。残りの4つは、名前を付けて渡すキーワード引数*です。
キーワード引数とは、sep="-"のように名前と値をセットで渡す引数のことです。print()の4つの引数は、必ずこの形で指定します。
print()は値を返さない¶
もうひとつ、意外と知られていない性質があります。print()は画面に表示するだけで、戻り値はNoneです。
result = print("hi")
print(result)
結果は次のとおりです。
hi
None
関数の結果を変数に入れたつもりが、Noneになっていたという経験はありませんか。表示することと値を返すことは別物だと覚えておくと、関数を作るときに迷いにくくなります。
4つの引数を表で整理しよう¶
細かい使い方に入る前に、4つの引数の役割を表にまとめました。全体像を先に押さえておくと、このあとの説明が頭に入りやすくなります。
| 引数 | 既定値 | 役割 | よく使う場面 |
|---|---|---|---|
| sep | 半角スペース | 値と値のあいだに入れる文字 | 日付やCSV風の出力 |
| end | 改行 | 最後に付け足す文字 | 改行せずに続けて表示 |
| file | None(標準出力) | 出力先 | エラー出力やファイル書き込み |
| flush | False | すぐに画面へ書き出すか | 進捗表示や長い処理のログ |
既定値のままでも困らないので、普段は意識しなくても大丈夫です。ただ、どれも知っていると書き方の選択肢がぐっと広がります。
sepで区切り文字を変える¶
sepは、値と値のあいだに入る文字を指定する引数です。separatorの略で、区切り文字という意味があります。
たとえば年・月・日を別々の値として持っているとき、ハイフンでつないで表示したいことがあります。sepを使えば、文字列を自分で組み立てなくても済みます。
print("2026", "10", "16", sep="-")
print("a", "b", "c", sep="")
結果は次のようになります。
2026-10-16
abc
空の文字列を指定すると、区切りなしでぴったりくっつきます。数値と単位をつなげて合計1200円のように表示したいときにも便利です。
文字列の+で連結するときの落とし穴¶
sepを知らないと、文字列を+でつなげて表示しようとしがちです。ところが数値が混ざると、次のようなエラーになります。
print("合計" + 1200 + "円")
# TypeError: can only concatenate str (not "int") to str
文字列と数値は、+でそのままつなげられないというエラーです。str()で変換してもよいのですが、print()にカンマで渡せば型の違いを気にせず表示できます。
print("合計", 1200, "円", sep="")
これで合計1200円と表示されます。もちろん、変数を文字列に埋め込むならf文字列も有力な選択肢です。
f文字列の使い方は、別の記事で詳しくまとめています。
【関連記事】Pythonのf文字列(f-string)の使い方
endで行の終わりを変える¶
endは、表示の最後に付け足す文字を決める引数です。既定値は改行なので、print()を呼ぶたびに次の行へ移ります。
ここに空の文字列を渡すと、改行せずに次の表示を同じ行へ続けられます。処理の途中経過を1行にまとめたいときに便利です。
print("読み込み中", end="")
print("...完了")
結果は次のとおりです。
読み込み中...完了
2回print()を呼んでいるのに、1行にまとまりましたね。end=" "のように空白を指定して、数字を横に並べる使い方もよく見かけます。
改行まわりの扱いは、文字列やファイル出力でもつまずきやすいポイントです。気になる方は次の記事もあわせてどうぞ。
【関連記事】Pythonの改行を初心者向けに解説
リストの中身をまとめて表示するコツ¶
リストをそのままprint()に渡すと、角カッコやクォートまで表示されます。デバッグには便利ですが、利用者に見せる表示としては少し味気ないですよね。
そこで覚えておきたいのが、リストの前に*を付ける書き方です。これはアンパックと呼ばれ、リストの要素をばらばらの値としてprint()に渡してくれます。
fruits = ["りんご", "みかん", "ぶどう"]
print(fruits)
print(*fruits, sep=", ")
print(*fruits, sep="\n")
実行すると、次のように表示が変わります。
['りんご', 'みかん', 'ぶどう']
りんご, みかん, ぶどう
りんご
みかん
ぶどう
sepと組み合わせると、カンマ区切りにも1行ずつの表示にも自由に切り替えられます。forループを書かずに済むので、ちょっとした確認にはとても手軽です。
なお、要素が文字列だけなら", ".join(fruits)でも同じ結果になります。数値が混ざっている場合はjoinだとエラーになるので、*を使うほうが気楽です。
ネストした辞書のように構造が深いデータは、print()よりpprintで整形したほうが読みやすくなります。
【関連記事】Pythonのpprintとは?ネストした辞書やリストを見やすく整形する方法
fileで出力先を変える¶
fileは、print()の出力先を決める引数です。何も指定しなければ、画面に表示される標準出力という出口が使われます。
ここにsys.stderrを渡すと、エラー専用の出口である標準エラー出力へ書き出せます。名前は難しそうですが、普通の表示とエラーを別の道に流すしくみだと考えれば十分です。
import sys
print("処理を開始します")
print("設定ファイルが見つかりません", file=sys.stderr)
画面で見るとどちらも同じように表示されます。けれども、プログラムの出力をファイルに保存したときなどに違いが出ます。
標準出力だけをファイルへ保存する設定にしていると、エラーのメッセージは画面に残ります。結果とエラーが混ざらないので、あとから原因を追いやすくなるのです。
ファイルへ直接書き込む¶
fileには、開いたファイルを渡すこともできます。write()メソッドを持つものなら何でも出力先にできる、というのがこの引数の考え方です。
with open("log.txt", "w", encoding="utf-8") as f:
print("1行目", file=f)
print("2行目", "続き", sep=" / ", file=f)
log.txtには、次の2行が書き込まれます。
1行目
2行目 / 続き
f.write()と違い、改行を自分で付けなくてよいのがうれしいところです。sepも同じように効くので、画面表示と同じ感覚でファイルに書き出せます。
flushで表示をすぐに反映させる¶
flushは、表示をすぐに書き出すかどうかを決める引数です。少しだけ、裏側のしくみの話をさせてください。
Pythonは、出力するたびに毎回画面へ書き出しているわけではありません。いったんバッファと呼ばれる一時置き場にためておき、ある程度たまったところでまとめて書き出します。
ふだんの画面表示では、改行のたびに書き出されることが多いので気になりません。ところが、end=""で改行をなくしたときや、出力をパイプやファイルへ流しているときは、表示が遅れることがあります。
進捗を1行で更新するサンプル¶
flush=Trueを指定すると、その場でバッファを書き出してくれます。進捗を同じ行で更新する表示を作ってみましょう。
import time
for i in range(1, 6):
print(f"\r進捗: {i}/5", end="", flush=True)
time.sleep(0.5)
print() # 最後に改行して終わる
先頭の\rは、カーソルを行の先頭に戻す特別な文字です。endで改行をなくし、flushですぐに表示することで、数字だけが書き換わっていくように見えます。
最後に引数なしのprint()を呼んでいるのは、改行だけを出力するためです。これがないと、次の表示が同じ行にくっついてしまいます。
実務でも、flushには何度か助けられてきました。私は10年ほどエンジニアとして開発に関わってきましたが、サーバー上で動かしたバッチ処理のログが、処理が終わるまで一行も出てこなくて焦ったことがあります。
原因は、出力がファイルへ流れていたためにバッファにためこまれていたことでした。flush=Trueを付けるか、python -uのようにオプションを付けて実行すると、こうした遅れを防げます。
print()とloggingの使い分け¶
ここまで見てきたように、print()はとても柔軟な関数です。では、どんな場面でもprint()を使えばよいのでしょうか。
学習中の小さなスクリプトや、動作の確認にはprint()で十分です。一方で、長く動かすアプリケーションのログには、標準ライブラリのloggingが向いています。
2つの違いを表で比べてみました。
| 観点 | print() | logging |
|---|---|---|
| 手軽さ | すぐ使える | 最初に少し設定が必要 |
| 重要度の区別 | できない | DEBUG・INFO・ERRORなどで分けられる |
| 時刻の付与 | 自分で書く | 書式の設定で自動化できる |
| 出力の止め方 | コードを消す | レベルを変えるだけ |
| 向いている場面 | 学習・ちょっとした確認 | 本番で動かすプログラム |
正直に言うと、私も若手のころはデバッグ用のprint()を消し忘れたまま、レビューに出してしまったことがあります。本番のログに意味のない数字が並んでいるのを見て、冷や汗をかいたのはよい思い出です。
それ以来、確認用の表示は消す前提で書くか、最初からloggingを使うようにしています。loggingの基本は次の記事で紹介しています。
【関連記事】Pythonのロギング(logging)入門。print卒業!プロが使うログ出力の正しい作法
print()まわりのよくある疑問¶
最後に、学習中によく聞かれる疑問をいくつか取り上げます。思い当たるものがあれば、ぜひ手元で試してみてください。
ひとつ目は、Python 2のコードで見かけるprint "hello"という書き方です。Python 2ではprintは文でしたが、Python 3から関数に変わりました。
この変更はPEP 3105という提案で決まったもので、関数にしたことでsepやfileのような引数を自然に追加できるようになりました。古い記事のコードを写してSyntaxErrorが出たら、カッコを付けてprint("hello")に直しましょう。
ふたつ目は、変数の名前と値をまとめて確認したいときの書き方です。f文字列の中で変数名の後ろに=を付けると、名前付きで表示できます。
name = "佐藤"
age = 28
print(f"{name=}, {age=}")
結果は次のとおりです。
name='佐藤', age=28
どの変数の値なのかが一目でわかるので、デバッグのときに重宝します。Python 3.8から使える書き方です。
三つ目は、print()での確認をそろそろ卒業したいという声です。処理を止めて変数の中身をじっくり見たいなら、デバッガーのpdbを試してみるのがおすすめです。
まとめ¶
print()は、Pythonを学ぶ人がいちばん最初に出会う関数です。けれども、sep・end・file・flushの4つの引数を知ると、できることがぐっと広がります。
区切り文字を変えたいときはsep、改行をなくしたいときはendを使います。出力先を変えたいときはfile、すぐに表示したいときはflushです。
さらに、リストの前に*を付けるアンパックを組み合わせれば、ループを書かずに中身を整えて表示できます。どれも1行で試せるものばかりなので、ぜひ今日書くコードで使ってみてください。
いつものprint()にひと工夫を加えるだけで、コードも出力も読みやすくなります。基本の関数を深く知ることは、遠回りに見えて確実な上達への近道です。
ここまでお読みいただきありがとうございました。