世界を動かす技術を、日本語で。

Fstrings.wtfは、Fストリングスに関するウェブサイトです。

概要

  • Python 3.13の f-string 動作に関するクイズの紹介
  • 問題が発生した場合は チケット作成 を推奨
  • 回答方法として 数字キーや矢印キー の利用案内
  • クイズの 作成者は@mitsuhiko、Claudeとの共同制作
  • ソースコードはGitHub で公開

Python 3.13のf-string挙動クイズ概要

  • Python 3.13で導入・変更された f-stringの挙動 に関するクイズ
  • 問題やバグを発見した場合は チケット作成 による報告を推奨
  • 回答方法として、 1/2/3/4の数字キー で素早く選択可能
  • 矢印キー で選択肢を移動し、 スペースまたはEnterキー で決定可能
  • クイズの 作者は@mitsuhiko、Claudeとの共同作成
  • ソースコード はGitHubで公開されているため、自由に閲覧・利用可能

Hackerたちの意見

文字列補間って、推論みたいな機能の一つだよね。以前に使ったことがあると、使わないのがすごくイライラするし、ちょっと追加すると心地よくなる。でも、もっと追加すると、どんどん改善されていく気がするんだけど、ある日気づくと、全く意味不明なものを見ていて「やばい、何をやってしまったんだ?」ってなる。これは珍しいことで、普通はコンピュータサイエンスではできるだけ多くのものを持ちたいと思うけど、数学的にはそれは文字通りか実際的に不可能だって言われる。でもここでは、どちらもひどくて許可されるべきじゃない。PythonやC#が選んだ一つの選択肢は、まあ、好みに任せるってこと。コメントなしの補間文字列で16ページの重層式を作っても動くけど、同僚たちは君の名前を呪って、君の破滅を企てるだろう。そういうことを強制すると、コードレビューで落ちることになるかもね。もう一つの選択肢は、例えば標準C++ 23では、最初の一歩すら拒否すること。リッチなフォーマットはできるけど、標準C++では補間は全く提供されない。6つのパラメータをフォーマットしたいなら、パラメータとして渡すしかない。Rustの「ほんの少しの補間」には満足してる。識別子だけ補間できるから、他の式はダメだけど、でもそれでも多くの人には物足りないかもしれないし、もちろん場合によってはそれじゃ足りないこともある。

純粋さと実用性は相反するもので、どの言語もそのバランスを見つけるのが難しいんだよね。正しいバランスは一つじゃないから、忙しい頭を持った人たちは、自分の意見を正しいバランスとして受け入れてほしいって思うのは避けられないよ。

CSはできるだけ多くのものを持ちたいけど、数学がそれを許さないんだよね。これがどのトピックと関係あるの?

Rustの解決策が嫌いなのは、全然解決策じゃないから。補間は限られたケースでしか機能しないから、常に今の状況で使えるかどうか考えなきゃいけないし、コードをリファクタリングする時に無限に手間がかかる。最低でも、フィールドアクセスで使えるようにするべきだと思う。一方、Pythonではこういうサイトの例があって面白い/変わってるけど、実際には誰も気にしてないし、みんなf-stringを楽しんでるよ。

文字列補間はその機能の一つで、これらの「WTF」の70%は文字列補間についてじゃなくて、ただPythonのstring.formatの構文についてだよ。 https://docs.python.org/3/library/string.html#format-string-...

これがJavaScriptの構文だったら、ほとんどのコメントは直感的じゃない構文や変な機能を嘆いてるだろうね。

そうだね、クイズが言いたい本当のポイントは、PythonもJavaScriptと同じくらい足元をすくうようなところがあるってことだと思ったよ。JSについてはこういうのを何度も見たからね。賛成とは言わないけど、ここでの主な議論になると思ってたんだよね…

でも、これがPerlだったら、みんな祝ってるだろうね。

すごい、何年もPythonに触れなくてよかったって思う。善意で地獄が舗装されてるって感じかな。たぶん、Justineはhttps://justine.lol/lex/を更新すべきだね。

何年もPythonに触れなくてよかったって思う。そんなこと言わないで、どの言語にも癖はあるよ。

これらの多くは望ましい機能だよね!

これがf-stringsの最初の特別な機能だよ:末尾にイコールサインを追加すると、式とその評価結果を表示できる。 >>> foo='bar'; print(f"{foo=}") foo='bar' へぇ、そんなことができるなんて知らなかった。

print(f)デバッグにはめっちゃ助かるね。 :)

Pythonのリリースノートは本当に読む価値があるよ。たいてい「ポジティブな驚き」があるし。=のサポートはPython 3.8で追加されたんだ: https://docs.python.org/3/whatsnew/3.8.html#f-strings-suppor...

デバッグ出力にはめちゃくちゃ一般的だよ。C++では、表現をそのままコピーするのが習慣になってる。引用符ありとなしの両方でね。情報量が多いし、考えなくてもいいから、まあ、まだその辺は頑張ってるけど。

関数のキーワード引数に対する同等の動作のPEPが受け入れられなかったのが悲しい。foo(bar=bar)を見るのは本当に一般的で、これがfoo(bar=)だったら、よりクリーンだと思うし、微妙な違いを見やすくすると思う。引数が単に通過してるだけじゃないケースが明らかになるからね。foo(bar=, …, baaz=baaz.get_id())だと、最も面白い詳細が見逃されにくくなるんだ。

それって「ワオ」って感じがするから、あんまり良いアイデアじゃないと思う。驚くような挙動を持つほどの価値はないし、バグの可能性が高いよね。自分でlocals()のサブセットを表示する関数を実装させるか、同じことをする標準関数を提供した方がいいと思う。

fstring.helpのどこかに埋もれてるトリックをいくつか学んだよ(^でセンタリング、#で0x/0b/0oプレフィックス、!aでascii)。ネストされたf-stringsの質問を見逃しちゃったのは、3.11のルールに縛られてたから。ネストされたf-stringsはまだ許可されてるけど、異なる引用符が必要なんだ(例えば、print(f"{f'{{}}'}")は動く)。これが3.12で整理されたみたいだね(バックスラッシュや改行などの他の制限も一緒に)。f-stringsは素晴らしいけど、文字列補間、古いスタイルの%フォーマット、新しいスタイルの.format()の微妙な違いを覚えるのはちょっと頭が痛いし、定期的にそれらを切り替えなきゃいけないケースもある(カスタム__format__メソッド、テンプレート文字列、ログなど)。エルゴノミックな新しいやり方があるのは素晴らしいけど、古い、洗練されてない解決策に戻らなきゃいけないのは本当にフラストレーションが溜まるよね。

これ、トリッククエスチョンだと思ってる。ネストしたf-stringsが同じ引用スタイルで来るのは知ってたけど、どのバージョンかは分からなかったんだ。今でも f'{f"{}"}' のトリックを使ってるのは、古いバージョンのPythonをサポートしたいから。うちのサーバーの一つはまだ3.10なんだよ。3.11は2027年までEOLにならないし。

普段は https://pyformat.info/ を参考にしてるんだけど、あそこはこんなに詳細には触れてないけど、合理的な内容は大体含まれてるよ。

Luaのf-stringライブラリを作ろうとした時に、いくつか学んだんだけど、f"{...}"とアザラシ演算子には驚かされたよ。これがWatに近くないのは嬉しいけどね。[1]: https://ezhik.jp/f-string.lua/ [2]: https://www.destroyallsoftware.com/talks/wat

そのライブラリ、めっちゃいい感じだね!

f-stringが登場する前からPythonをちゃんと書いてなかった私だけど、f-string特有の構文はほぼ全部当てられた。でも、いくつかの式の戻り値に関するエラーをたくさん犯しちゃった。もしかして、f-stringがPythonで一番「なんじゃこりゃ」じゃないことなのかな? :)

URLはともかく、これらの中でWTFだと思うのはほんの数個だけ。特に質問20と21は間違いなくWTFだね。>>> a = 42 >>> print(f"{a:=10}") 42 >>> print(f"{(a:=10)}") 10 アザラシ演算子が良いアイデアだと思った人がいるなんて、まだ信じられないよ。

これはアザラシ演算子とは関係なく、Pythonのstring.formatの動作に関することだよ。 https://docs.python.org/3/library/string.html#format-string-... 編集: 誰かが私をダウンボートしたのは、ここにアザラシ演算子がないことを理解してないからだね。print(f"{a:=10}")

16/26 Pythonはあんまり書かないけど、f-stringsはわかってると思ってたんだよね。でも、全然ダメだったわ。まだ3.6のモードで考えてるみたい。