効率良いコーディングのためにPython文字列リテラルを改めて理解してみる

Pythonの文字列リテラルについて、わかったつもりでわかっていないことを実感して再確認しました。
2020.02.27

はじめに

Pythonで文字列を扱う際に、reモジュールのmatch関数にraw-strings(r)を渡したり、Python3.6以降での整形文字列にf-strings(f)を使ったりと、特定の文字をプレフィックスとして使うことがあります。

import re
if re.match(r'Hello', 'Hello world'):
    print('Match')
> Match
phrase = 'Tomorrow'
print(f"{phrase} and {phrase}")
> Tomorrow and Tomorrow

re.match()へ渡すraw-stringsにf-stringsを使うにはどうすればいいものかと思い、公式ドキュメントを含んで辿ってみました。

文字列リテラルについて

先述したfやrは、文字列リテラルの stringprefix と呼ばれるものです。Python3.6で利用可能なプレフィックスは以下の通りです。

u""
U""
r""
R""
f""
F""
rf""
rF""
Rf""
RF""
fr""
fR""
Fr""
FR""

大文字と小文字で扱いに差はありません。rfrfをあわせたものとなり、frと記述した場合でも変わりません。unicodeリテラル(u)についてはPEP 414に、以下の通り3.3から再サポートされるようになったと記載されています。

However, since the proposal is for a comparatively small tweak to the language syntax with no semantic changes, it is feasible to support it as a third party import hook. While such an import hook imposes some import time overhead, and requires additional steps from each application that needs it to get the hook in place, it allows applications that target Python 3.2 to use libraries and frameworks that would otherwise only run on Python 3.3+ due to their use of unicode literal prefixes.

2. 字句解析 — Python 3.8.2 ドキュメント

Python2ではurのprefixも存在しましたが、Python3ではuリテラルが異なる挙動となっているため非互換です。

# python2
print(ur'test')
> test

# python3
print(ur'test')
File "<stdin>", line 1
    print(ur'test')
                 ^
SyntaxError: invalid syntax

raw-stringsリテラルとf-stringsリテラル

エスケープシーケンスを展開せずに、そのままf-stringsに渡す形となります。

if fr'Hello\t' == 'Hello\t':
    print('Matches')
# Hello\t == Hello[tab]
> 

if f'Hello\t' == 'Hello\t':
    print('Matches')
# Hello[tab] == Hello[tab]
> Matches

あとがき

普段あまり意識することがない箇所であり、文字列リテラルについてドキュメントを触る良い機会となりました。

エスケープシーケンスについて意識するのはファイルパス等が主になると思います。大体嵌ると中々解決し難い箇所であるため、出力例等参考になれば幸いです。