検索
連載

[Pythonクイズ]f文字列・raw文字列・バイト列……混ぜてOKな組み合わせはどれ?Pythonステップアップクイズ

文字列やバイト列を囲むクオート文字の前にはいろいろなプリフィックスを置けますよね。それらの中には混ぜてもいいのがあるって知っていましたか?

PC用表示 関連情報
Share
Tweet
LINE
Hatena
「Pythonステップアップクイズ」のインデックス

連載目次

例外を発生させる書き方はドレかな?
例外を発生させる書き方はドレかな?

【問題】

 以下は文字列やバイト列を変数に代入するコードだ。4つのコードのうち、間違った書き方をしているものはどれか。

# 選択肢1
s = u'あいうえお'

# 選択肢2
path = 'windows'
s = f'c:\\{path}\\system32'

# 選択肢3
b = rb'GET\s+/(.+)\s+HTTP/1\.1'

# 選択肢4
path = b'windows'
b = bf'c:\\{path}\\system32'

例外を発生させる書き方はドレ?

第5の選択肢?

 もともと、この問題の画像には「文字列/バイト列の間違った書き方はドレかな?」ではなく「Python 3.13で例外となる文字列/バイト列の書き方はドレ?」みたいなことが書いてありました。そして、5番目の選択肢を用意していたのです(それ以外の選択肢は全て例外が発生しないものにして)。つまり、Python 3.14で導入されるアレを想定したクイズにしようと考えていました。が、それはいくらなんでもナニだなぁと思って、その選択肢はボツにしちゃいました。

 ということで、ChatGPT(GPT-5)/Gemini(Gemini 2.5 Flash)/Claude(Claude Sonnet 4)という3つのLLMに「このクイズはもともと『Python 3.13で例外となる文字列/バイト列の書き方はドレ?』という問題で、Python 3.13までの処理系では例外を発生させる選択肢を追加するハズでした。もともとの問題文を手掛かりに、どんな選択肢を追加するつもりだったのかを考えてみてください」というプロンプトを与え、その後、各LLMと対話を重ねながら、筆者の想定するような選択肢を彼らが考え出せるかどうかを試してみました。

結果は記事の最後で!
結果は記事の最後で!

 LLMとの問答の結果はどうだったのでしょうか? 結末は最後で!(2回続けてこのパターンか……。ちょっとやり方を考えないと!)。



かわさき

 どうもHPかわさきです。

 今回は本文よりも先にLLMとの問答とその結末部分が書き上がるという普段とは逆の執筆スタイルになりました。たぶん、問題を考えた時点で「この問題をどうやってLLMに絡ませたらいいんだ?」と自問自答した結果、本文よりもそっちを優先しないと原稿が書き終わらないと思ったんでしょう。何だかその分、いつもよりもそっちの方が分量多めな気がしますが、楽しく読んでもらえるとうれしいです(楽しいかどうかはさておき)。


【答え】

 例外を発生させるのは選択肢4の「bf'c:\\{path}\\system32'」という表記でした。

バイト列を意味する「b」とフォーマット済み文字列を意味する「f」は同時には指定できない
バイト列を意味する「b」とフォーマット済み文字列を意味する「f」は同時には指定できない

 バイト列を意味する「b」とフォーマット済み文字列(f文字列)であることを意味する「f」は同時には指定できません。

【解説】

 Pythonでは文字列やバイト列を囲むクオート文字の前に「u」「r」「f」「b」というプリフィックスを前置でき、そのうちの幾つかは同時に指定することが可能です。

プリフィックス 意味 同時に使用できるプリフィックス
u Unicode文字列であることを意味する。Python 2との互換性のためにPython 3でも使用できる なし
r エスケープ文字をそのままの意味で解釈するraw文字列またはrawバイト列であることを意味する。例えば、「r'\n'」は1文字のバックスラッシュと1文字の小文字のnが続く文字列となる bまたはf(両方を同時には指定できない)
f フォーマット済み文字列(f文字列)であることを意味する。f文字列の置換フィールドにはそこに記述した式(変数や関数呼び出し、単純な計算式など)の値が埋め込まれる rのみ
b バイト列であることを意味する。バイト列の各要素は0〜255の範囲の整数値となる rのみ
クオート文字の前に置けるプリフィックス

 同時に使用可能なプリフィックスについてはどちらを先に書いても構いません。また、「r」と「b」と「f」の3つを同時に前置することはできません。なお、上の表では小文字のみを記載していますが大文字を使っても構いません(ですが、あまり使われてはいないような気がします)。

 というわけで各選択肢について簡単に見ていきましょう。

 選択肢1では「u」というプリフィックスを使っています。「u」はそれがUnicode文字列であることを意味しますが、これはPython 2では文字列にstr型とunicode型の2種類があったことに起因します。ここを深く掘り下げると大変なことになります(主に筆者が)。

 よって、Python 2でUnicode文字列を使うときには「u」というプリフィックスを使ったこと、Python 3ではstr型はUnicode文字列を格納していること、そのため(特にPython 2からPython 3への移行期に)Python 2のUnicode文字列をPython 3でもうまく取り扱えるようにこのプリフィックスが残されたと考えるとよいでしょう。もちろん、普段はこれを使う必要はありません。

 以上のことから、選択肢1は例外を発生しません。

 選択肢2にある「f'c:\\{path}\\system32'」は今では多くの人が普通に使っているf文字列です。これは特に何をいうまでもなく問題ないでしょう。

 選択肢3の「b = rb'GET\s+/(.+)\s+HTTP/1\.1'」では「rb」というプリフィックスが使われています。これはrawバイト列です。バイト列の内容自体について深くは語りませんが、恐らくはネットワーク経由で送られてきたバイトストリームをパターンマッチするつもりなのでしょう。このときには、rawバイト列内に書かれているバックスラッシュはエスケープ文字としてではなく、そのままバックスラッシュとして解釈されます。「r」がないと、これは「b = b'GET\\s+/(.+)\\s+HTTP/1\\.1'」のように書く必要があります。もちろん、この記述も例外を発生しません。

 選択肢4の「b = bf'c:\\{path}\\system32'」では「bf」というプリフィックスが使われていますが、これは上の表にあるように同時に指定はできません。そのため、例外が発生します。

 実はPython 3.14では新たにテンプレート文字列(t文字列)という機能が導入される予定です。これについては「Python 3.14.0rc2/3.13.7リリース:Python 3.14のテンプレート文字列についても解説」で簡単に紹介しているのでそちらもぜひ読んでみてくださいね。


かわさき

 一発で正解が返ってくるとは思っていなかったのですが、やはりどのLLMも苦労していました。「Python 3.13で」というところに着目して、多くのLLMが「Python 3.13で、ということはPython 3.12までは例外にならないけれど、Python 3.13から例外になるようになった要素だな」という発想からPythonの仕様を自由に改変した答えを考え出していました(笑)。

 各LLMとのやり取りの中では、例えばChatGPTさんは「\nや\tなどのエスケープシーケンスとf文字列の相互作用が問題になり、Python 3.13では構文エラーになります」と述べ、その例として「s = f"c:\newfolder"」が例外になるといってきました(なりません)。Geminiさんはf文字列にバイト列を埋め込もうとするとSyntaxError例外になるといいました(なりません)。ClaudeさんはPython 2にあったur文字列がPython 3.13で突如復活するも、Python 3.14では廃止されることになったといいました(んなこたーない)。

 そんなこんなを経まして、Python 3.14の新機能であることを伝えたところ、ChatGPTさんとClaudeさんは何とか正解へとたどり着きました。が、Geminiさんにはちょっと無理でした。

 というわけで、筆者が5番目の選択肢として考えたのは以下です。

world = 'world'
t = t'hello {world}'

Python 3.14で導入されるt文字列(テンプレート文字列)

 Python 3.14で追加されるt文字列(テンプレート文字列)です。これはPython 3.13では例外になります。当たり前ですね。ダメなプロンプトとダメな推量が合わさるとダメな結果が得られることがよく分かったのでした。

2つのLLMは何とかt文字列にたどり着くも、Geminiさんには無理でした
2つのLLMは何とかt文字列にたどり着くも、Geminiさんには無理でした

 上でも紹介していますが、Python 3.14.0rc2のリリースに関する解説記事の中でt文字列についても触れています。こちらもご参照ください。


「Pythonステップアップクイズ」のインデックス

Pythonステップアップクイズ

Copyright© Digital Advantage Corp. All Rights Reserved.

[an error occurred while processing this directive]
ページトップに戻る