Python
python3

Pythonにおける % と str.format() 。どっちを使うの?

当座の理解としては

おそらく「どっちでもいい」です。チームに依ると言っても良いでしょう。

  • str.format() は導入当初 %-style を置き換える意図がありました。
  • 実際に str.format() の方が推奨されていた時期もあるようです。
  • 現時点では、どちらを推奨とされているか、明示的な規定はないように見受けられます。
  • 将来どうなるかは分かりませんが、直近で %-style が消えるという議論にはなっていません。

日本の書籍より

Python本の隠れた(失礼!)名著『Python文法詳解』にこうあります (p128)

Python3.2までは、Pythonチュートリアルなどで「古い%演算子による文字列化は、いずれ削除されます」とされていましたが、Python3.3ではこの記述が削除されています。

同著のこの記述から「あー、そうなのか。だとするとどっちを使っても非ということもなさそうだな」と理解してました。

そこが本稿筆者のスタートラインです。

公式ドキュメントではではどう記載されているか

公式ドキュメントの隅から隅まで見通すと結論が変わる可能性がありますが、その上で目に止まった面白い点を以下に書いておきます。

https://docs.python.org/3.2/library/stdtypes.html#old-string-formatting

最初のNote部分の変遷が面白いのでその部分を全文掲載します。以下では、特に注目したい部分は太字にします。

Note: The formatting operations described here are modelled on C’s printf() syntax. They only support formatting of certain builtin types. The use of a binary operator means that care may be needed in order to format tuples and dictionaries correctly. As the new String Formatting syntax is more flexible and handles tuples and dictionaries naturally, it is recommended for new code. However, there are no current plans to deprecate printf-style formatting.

「推奨されていますが削除予定はない」となっています。前掲著とはちょっと意味合いが違いますが、patchで変わったのかもしれません。

いずれにせよポイントは「推奨されている」と確かに書かれていること。これを根拠に「str.format()が推奨されている」ということを主張出来た時期はあったと言えます。

さて 3.3系です

https://docs.python.org/3.3/library/stdtypes.html#old-string-formatting

Note: The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer str.format() interface helps avoid these errors, and also provides a generally more powerful, flexible and extensible approach to formatting text.

「C言語のprintf()の文法に基づく」みたいな説明がまるっと消えてますがそれはともかく。

「推奨」の言葉も消えてます。ただし「パワフルだよ!」とありまして、まぁこれは否定するのは難しいかと思います。事実混乱を招くほどパワフルですし。

3.6です。現在の最新です。

https://docs.python.org/3.6/library/stdtypes.html#old-string-formatting

Note: The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals or the str.format() interface helps avoid these errors. These alternatives also provide more powerful, flexible and extensible approaches to formatting text.

「common errors」というのは例えばこれとかでしょうか。「common errorsを回避できるかもよ」ということから、推奨とは書かれてないものの str.format() の方が良いよ、みたいなニュアンスは伝わってきます。

まだリリースされていない3.7系を見てみます。

https://docs.python.org/3.7/library/stdtypes.html#old-string-formatting

Note: The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals, the str.format() interface, or template strings may help avoid these errors. Each of these alternatives provides their own trade-offs and benefits of simplicity, flexibility, and/or extensibility.

「str.format()推奨」から「それぞれに良い点・悪い点があるよ」みたいな表記まで追加されました。筆者目線ですと隔世の感ある一文です。

このNoteが仕様の全てを記載していないことには注意が必要ですが、テンションは伝わってくる気はします。逆に、もし他の箇所で結論が変わる文があれば是非指摘頂きたく。

元のPEPでは入れ替えることを意図していた

https://www.python.org/dev/peps/pep-3101/

This PEP proposes a new system for built-in string formatting operations, intended as a replacement for the existing '%' string formatting operator.

Python 3.0の頃はもっと野心的だったのでしょう。ただ、printf()とのアナロジーの人気が強いことからこの「replace」という議論自体が縮退している印象です。

書籍ではどうか

「python format recommended」などとググるとGoogle Books経由で『Mastering Python』という書籍の以下の記述が目に留まりました。

In general most people str.format these days, but it mainly comes down to preference. The printf-style is simpler, while the str.format method is more powerful.

ちなみに同著の著者はprintf()の流れから%-styleが好きなようです。

本稿筆者はどう思っているか

自分では原則として str.format() しか使用していません。人に教える際に %-style を省略するということもしばしばです。

ただ、それは「推奨されているから」という意味合いよりは、漠然とした好みの問題かなと思います。%-styleを使われるとウッとするのもまぁ同時に事実ですが、他人に「使うな」と言うには、私としては説得材料が足りない印象を持ちます。

チーム内での一貫性を求めるために統一するなら str.format() を強く推します。ただ、仮にどっちでも良いというコーディングスタイルであればそれに従って双方扱えるようにしておくのが筋と考えます。チラ見したところ、GoogleのStyle Guideですと「両方OK」となっていました (Revision 2.59)。

ここで言いたいのは、Python公式のドキュメントを根拠にする限り「%-styleを使っている人に str.format() 使えよ」という圧力をかける筋合いはあまりなさそうだ、ということです。新しいもの好きなのは分かるし、 str.format() の方がパワフルなのも理解出来ますが、それ以上の「上から目線」を %-style に対してする意義はないなぁと。

一方 str.format() を知るとどうしてもそういう目線で %-style を見てしまうのです。過去の議論から「公式に推奨され、入れ替え予定になっていた」事実が余計にそういう目線を付加するのかなぁ、なんて思ったりします。

前掲著『Mastering Python』は面白い表現で「逃げて」いる気はします。Python公式としての推奨ではないけど多くの人が推奨している、というところ。この二つの差は大きいかもしれません。「Pythonの開発元が公式に推奨しており、将来的に%-styreが削除される」という意味における推奨なら是非もなく「%-style は使うべきでない」という議論になるわけですが、今はそういう流れにはなってなさそう、というのが本稿の当座の結論です。

漠然と「str.format()が推奨されている」という表現を耳にしますが、これを事実とするには少々怪しい(現時点では明確な根拠がない)と考えます。将来は不明ですが、他言語との接点という面もあって、 %-style が廃れるのはちょっと考えづらい感はあります。

あいにく筆者が仕様全文を読んでいるわけではないこと、開発者自身でもないことから、この辺りについてこの文章が結論を出せることはありません。新情報お待ちしております。

この件について「すごくどうでも良い」という意見には同意します。で、本文を最後まで読んだの……? :-)

その他の情報源

  • https://pyformat.info/ ... 両方のフォーマットでの記載方法が並べられており秀逸です

追記 (2017-08-31)

  • 2016年かどっかのPyCon JPで %-style を削除する予定は「ない」という話があったとかなかったとか。情報お待ちしております。
  • Python 3.7 で導入された f-strings との関係に興味を持つ方が複数いらっしゃったのですが(コメント等ありがとうございます)、 %-style と str.format() の関係についての議論が深まるわけでもないことなどから本稿では扱っていません。何らかの意見を表明するには実践をベースにした経験談等が手元にありません。