Python3.12のf文字列(f-string)の変更点を確認する

Python3.6系から文字列をフォーマットできる機能として、f文字列(f-string)が追加されて、%str.format()よりも便利に記述できるようになっています。

そのf文字列がPython3.12からより使いやすくなるような変更が入ったようだったので、調べて内容を軽くまとめました。

詳しくは以下公式リファレンスに記載されています。

https://docs.python.org/ja/3/whatsnew/3.12.html#pep-701-syntactic-formalization-of-f-strings

クォートの再利用

まず、クォートを再利用できるようになっていました。

例えば、" をf文字列とf文字列内の辞書で2回利用しようとした場合、Python3.11の場合は以下のようにエラーになります。

>>> my_name = {"first_name": "John", "last_name": "Smith"}
>>> print(f"Hello, My Name is {my_name["first_name"]} {my_name["last_name"]}.")
  File "<stdin>", line 1
    print(f"Hello, My Name is {my_name["first_name"]} {my_name["last_name"]}.")
                                       ^^^^^^^^^^
SyntaxError: f-string: unmatched '['

このように記述したい場合、f文字列で利用したものとは異なるクォートにする必要がありました。

print(f"Hello, My Name is {my_name['first_name']} {my_name['last_name']}.")

このクォートの再利用が3.12からは成功するようになっていました。

print(f"Hello, My Name is {my_name["first_name"]} {my_name["last_name"]}.")

また、再利用ができるようになったことで、ネストしたf文字列も記述できるように変化していました。

f"{f"{f"{f"{f"{f"{友ヶ島が聖地の1つ}"}"}"}"}"}"

Python3.12の場合は成功する

Python3.11の場合は以下のようになる

>>> f"{f"{f"{f"{f"{f"{友ヶ島が聖地の1つ}"}"}"}"}"}"
  File "<stdin>", line 1
    f"{f"{f"{f"{f"{f"{友ヶ島が聖地の1つ}"}"}"}"}"}"
         ^
SyntaxError: f-string: expecting '}'

3.11までは以下のようにする必要があるようでした。

f"""{f'''{f'{f"{友ヶ島が聖地の1つ}"}'}'''}"""

ネストしているコードの元は公式リファレンスのサンプルコードで、初めて見た時は何をしているのかわかっていませんでしたが、以下のクォートをそれぞれ利用していたのだとよく見たらわかりました(なので、上述のネストまでしか従来はできなかったんだなと理解しました)。

  • """"""
  • ''''''
  • "
  • '

複数行に渡りf文字列を定義 + コメントの記述ができるようになった

以下のような構文が使用可能になっていました。

>>> f"Summer Time Rendering Charactor: {", ".join([
...     'Shinpei',  # 網代 慎平
...     'Ushio',    # 小舟 潮
...     'Mio'       # 小舟 澪
... ])}"
'Summer Time Rendering Charactor: Shinpei, Ushio, Mio'

上記の構文だとPython3.11の場合、SyntaxError: unmatched ']'となることが確認できました。 これで、より柔軟にf文字列を利用できそうでした。

バックスラッシュとUnicode文字の利用

以下のような構文が利用できるようになっていました。

バックスラッシュの例

>>> setting = ["和歌山", "加太", "友ヶ島"]
>>> print(f"This is setting: {"\n".join(setting)}")
This is setting: 和歌山
加太
友ヶ島

Unicode文字の例

>>> print(f"This is setting: {"\U+2B50聖地\U+2B50️".join(setting)}")  # print(f"This is setting: {"⭐聖地⭐️".join(setting)}")
がエスケープされた表記
This is setting: 和歌山 ⭐ 聖地 ⭐ 加太 ⭐ 聖地 ⭐ 友ヶ島  

Python3.11までは、それぞれ以下のようになります。

SyntaxError: unexpected character after line continuation character
SyntaxError: invalid character '⭐' (U+2B50)

2つ目の例は実務で利用するケースは少なそうですが、バックスラッシュも利用できるのはより柔軟になった印象を持ちました。 実際に利用する場合、コメント・バックスラッシュあたりが特に便利になりそうかな?と思ったので、利用できそうなケースがあれば使ってみます。

余談

PEP 701で提案されていたようだったので少し覗いてみました。

https://peps.python.org/pep-0701/

導入当時は正式に文法として定義されていなかったことが一番の要因だったようだと読み取りました。

3.12もリリースされてしばらく経つため、最新の情報ではないですが追いかけるのは楽しいですね。