🍲
Python の f 文字列の、やや思いがけない挙動
これは何?
Python の f 文字列の挙動が、ちょっとおもしろかったので記録しておく。
事例
基本?
Python3.13
f"{1.1:{1}}"
#=> '1.1' ... わかる気がする
f"{1.1:{1.0}} / {1.1:{1.1}} / {1.1:{1.2}}"
#=> '1e+00 / 1e+00 / 1.1' ... よくわからない
数値なのか
Python3.13
f"{1.1:{1.9}} / {1.1:{1.10}} / {1.1:{1.11}}"
#=> '1.1 / 1e+00 / 1.1' ... そうきたか
f"{1.1:{1e1}}"
#=> ' 1e+00' ... なるほど
大きな数値
Python3.13
len(f"{1.1:{1e2}}")
#=> 100 ... ですよね
len(f"{1.1:{1e16}}")
#=> ValueError: Invalid format specifier '1e+16' ... 1e16 は "100略0.0" にはならないのでエラー。
len(f"{1.1:{1e13}}")
#=> Python がクラッシュ。メモリが足りなかったのかな。
計算してみる
Python3.13
f"{1.1:{1.1*2}}" #=> '1.1'
f"{1.1:{1.1*3}}"
#=> ValueError: precision too big ... 1.1*3 は 3.3000000000000003 になる
f"{1.1:{1.1*4}}" #=> ' 1.1'
あるいは
Python3.13
len(f"{1.1:{1e2/7}}")
#=> ValueError: precision too big ... 小数点以下が長すぎるかな
len(f"{1.1:{1e8/7}}")
#=> 14285714 ... 14285714.285714285 なら OK らしい
符号
Python3.13
f"{1.1:{'+0.0'}} / {1.1:{'-0.0'}} / {1.1:{'0.0'}}"
#=> '+1e+00 / 1e+00 / 1e+00' ... それはそう
f"{1.1:{+0.0}} / {1.1:{-0.0}} / {1.1:{0.0}}"
#=> '1e+00 / 1e+00 / 1e+00' ... "+" は無視される
感想
昔の PHP で感じた手触り。
あんまり Python は使わないのでよく知らないんだけど、
f{a:{b}} は、b という式の評価結果を文字列化したものを書式として a を出力するということみたい。
b が文字列じゃない場合はエラーにしたほうがいいんじゃないの? と思ったんだけど、 {式} が「式の評価結果を文字列化する」だから仕方ないのかな。
そこに {数値} などと書かなければ良いので、困ることは稀なんだと思う。
Discussion