Pythonのprintで改行なしで出力するには?endキーワード引数に空文字列を指定します

293, 2021-07-25

目次

Pythonのprintで改行なしで出力するには?

Pythonのprint()を使っていて改行をしたくない場合があります。
そういう場合は↓のようにprint()のキーワード引数endに空文字列を指定します。

print('Hello, World!', end='')
# Hello, World!

↑のようにするとprint()は行末に改行を付加しません。

この記事ではprint()のキーワード引数endとその関連機能の使い方を見ていきます。
具体的には↓を見ていきます。

  • endに行末の文字列を指定する

  • sepにセパレーターを指定する

  • sepとendの連携

  • endのCPythonによる実装を見てみる

関連記事
Pythonのprint関数の素晴らしさをここに示す

endに行末の文字列を指定する

print()のキーワード引数endには行末の文字列を指定することが出来ます。
これは空文字列だけに限りません。
たとえば行末を「セミコロン + 改行」で終わらせたい場合は↓のようにします。

print('Hello', end=';\n')
# Hello;

↑の場合はHelloという文字列が出力されますが、そのお尻に「;\n」が付加されます。
このようにendには特定の文字列を指定することが可能です。
つまり↓のようなprint()も合法だということになります。

print('Hello', end=';\nWorld;\n')
# Hello;
# World;

ただ↑のような引数の指定はコードをわかりにくくするかもしれません。

やり過ぎ注意

sepにセパレーターを指定する

endキーワード引数に似ている役割を持つのがsepキーワード引数です。
これはprint()に渡される各引数のセパレーターを指定できるキーワード引数です。
print()sepキーワード引数にカンマ(,)を指定すると↓のようになります。

print('One', 'Two', 'Three', sep=',')
# One,Two,Three

↑の場合、「One」「Two」「Three」というのがprint()で出力される引数です。
sepには「,」を指定しているので、それぞれの引数の間にこの文字列(セパレーター)が挿入されます。

sepとendの連携

sependを連携すると特定のフォーマットの文字列を出力することが出来るようになります。
たとえばカンマで区切られて行末がセミコロンで終わるというフォーマットで出力したい場合は↓のようにします。

print('One', 'Two', 'Three', sep=',', end=';\n')
# One,Two,Three;

endのCPythonによる実装を見てみる

Pythonの実装はいろいろありますが、その内の1つであるCPythonによるprint()の実装を見てみたいと思います。
CPythonはPythonのC言語による実装です。
print()関数の実装は、Python/bltinmodule.cにあります。

このモジュール内のbuiltin_print()というのがprint()の実装です。
このbuiltin_print()内のキーワード引数endの実装を追ってみましょう。

まずendというPyObjectが関数の先頭で定義されています。

    PyObject *sep = NULL, *end = NULL, *file = NULL;

このendという変数に関数の引数であるkwnamesが展開されて、値が保存されます。
builtin_print()は関数の引数を一通り出力したあとにend変数の出力処理に移ります。
これは↓のようなコードです。

    if (end == NULL)
        err = PyFile_WriteString("\n", file);
    else
        err = PyFile_WriteObject(end, file, Py_PRINT_RAW);

↑のコードを見ると、endNULLだったら改行を出力し、NULLでなかったらendもファイル(出力先)に書き込んでいるのがわかります。
PyFile_WriteString()はファイルに文字列を書き込み、PyFile_WriteObject()はファイルにPyObjectを書き込む関数のようです。
filePyObjectですが、これには指定が無かった場合はstdoutのオブジェクトが保存されます。
ちなみにこのfileprint()のキーワード引数で、特定のファイルオブジェクトを指定することが出来ます。

errというのはint型の変数でこれが真の時、↓のようにreturn NULL;されます。

    if (err)
        return NULL;

最後にend変数のバリデーション部分を確認してみましょう。
end変数は出力前にその値をバリデーション(検証)されます。

    if (end == Py_None) {
        end = NULL;
    }
    else if (end && !PyUnicode_Check(end)) {
        PyErr_Format(PyExc_TypeError,
                     "end must be None or a string, not %.200s",
                     Py_TYPE(end)->tp_name);
        return NULL;
    }

↑のコードを見ると、endNoneだった場合はendNULLが代入されています。
そしてPyUnicode_Check()の結果が偽だった場合は例外が発生しているのがわかります。
エラー内容は「end must be None or a string, not xxx」という内容です。
エラー内容から察するにPyUnicode_Check()endがユニコード文字列かどうか確認する関数のようです。

本当にこのコードの通りエラーが発生するのでしょうか?
ためしに↓のようなコードを実行してみます。

try:
    print('Hello', end=1)
except TypeError as e:
    print(e)

↑のコードを実行すると↓のような結果になります。

end must be None or a string, not int

さきほどのC言語のコードの通り、例外が送出されました。

おわりに

今回はPythonのprint()で改行なしで出力する方法を見てみました。
改行なしの出力はprint()endキーワード引数に空文字列を指定することで実現できます。

The End