LoginSignup
24
19

More than 5 years have passed since last update.

Pythonでオブジェクトを文字列化する6つの方法

Last updated at Posted at 2017-09-06

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

上についてf-stringsという言及があったのですが、文字列化する方法はそれだけではない気がします。メモ的に思いつくものを挙げます。

str() と repr()

>>> import datetime
>>> d = datetime.datetime(2017, 9, 1, 12, 12, 0, 0)
>>> str(d)
'2017-09-01 12:12:00'
>>> repr(d)
'datetime.datetime(2017, 9, 1, 12, 12)'
>>> eval(repr(d))
datetime.datetime(2017, 9, 1, 12, 12)

repr(obj) によって内部では obj.__repr__() が呼ばれ、str(obj)によって内部では obj.__str__() が実装されていればそれが、なければ obj.__repr__() が呼ばれて代わりに使われます。

repr(obj) の結果は、可能であればPythonの式(expression)とすることが期待されますが、いつもそうとは限りません。上述のdatetimeの例では eval() で評価できる文字列が返ってきています。

str(obj) の結果はPythonの式であるべきみたいな要請はなく、人が読みやすいフォーマットであることを優先するのが一般的です。

「オブジェクトを読みやすい文字列に直す」というと、例えばpprintモジュールなども思いつきます。そちらはobj.__repr__()を利用するようです。まぁ__str__()の結果から構造を把握するのは無理だわな。

%演算子と文字列メソッド str.format()

上の記事の主題でした。普段の開発上では最も重要な気がしますが、省略。

f-strings

Python 3.6 より導入された記法で、文字列の中にPythonの式を直接記述できるようにするものです。

PEP 498 -- Literal String Interpolation

FizzBuzzの例です。

>>> print(*[f"{'Fizz'*(not i%3)}{'Buzz'*(not i%5)}" or i for i in range(1,31)], sep='\n')
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz

Redditの「a Py3.6 fizzBuzz oneliner with f-strings」を参考にしていますが、map()よりはリスト内包表記を使う方が最近しっくりするのでそちらに変えました(reduce()がライブラリ落ちしたのもあります)。

念のため、print()の引数の頭にある*はリストのアンパックを示します。

型チェックという点では、少なくともmypy 0.521 はf-stringsの中身を見ます。

$ mypy --version
mypy 0.521
$ cat /tmp/test.py
def func(a: int) -> int:
    return a ** 2

print(f'{func(10.0)}')
$ python /tmp/test.py
100.0
$ mypy /tmp/test.py
/tmp/test.py:4: error: Argument 1 to "func" has incompatible type "float"; expected "int"

残念ながら筆者は3.5以前を使う機会も多いため、率先してこれだけに統一するという状況には至ってません。
ただ、将来的には str.format() を押しのけて f-strings が中心になる可能性はあるかなと思います。

テンプレート文字列

https://docs.python.jp/3/library/string.html#template-strings

昔からある機能として$変数を置き換えるというテンプレート文字列の機能がPython組み込みにあります。上記のサンプルを軽く紹介しときます。

>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'

あいにくHTMLエスケープ等はサポートしていないです。個人的にめったにお目にかかりませんが、使用を検討したことはあります。

その他

タイトルでは6つとしましたが、Python標準の機能だけでもまだあります。

  • pprintモジュール
  • 組み込み関数 format() (コメントいただきました。筆者は知りませんでした。 参考)
  • (他にあればご指摘ください……)

jinja2などの外部ライブラリを使用すれば文字列化する方法は他にもあるはずです。もちろん自前で作ればその分選択肢は増えます。

24
19
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
19