Formatted string literals (続き)
ここをもう少し見てみる
f_expression ::= (conditional_expression | "*" or_expr) ("," conditional_expression | "," "*" or_expr)* [","] | yield_expression
6. Expressions — Python 3.7.3 documentation は上のほうが葉に近い要素の定義で、ボトムアップな順で定義されているようだ
conditional_expression ::= or_test ["if" or_test "else" expression]
expression ::= conditional_expression | lambda_expr
conditional_expression
はif式で、それにlambda式を加えた
expression
が一般の式になるということだろう
逆に見ると、formatted stringの{}
内に書ける式(f_expression
)は
lambda式以外の一般の式に加え、*
or_expr
やyield式を書けるということ
(yield式は一般の式に含まれてないのか)
*
or_expr
ってなんだろう
or_expr
っていうのはざっくりいうと比較演算が入らない式
アンパッキングみたいなものかと思ったけど違うみたい
>>> l = [1, 2, 3]
>>> f"{l}"
'[1, 2, 3]'
>>> a, *b = l
>>> a
1
>>> b
[2, 3]
>>> f"{*l}"
File "<stdin>", line 1
SyntaxError: can't use starred expression here
f"{*l}"
でも構文的にはあってると思うんだけど
アンパッキングは左辺だしここでは右辺値だから違うんだよな
右辺値にアスタリスクが出てきたら何だっけ
関数の引数リストで引数にアスタリスクをつけると可変長引数だったりするけど
使い方がわからない
普通のアンパッキング用の定義(らしきもの)は別の個所で出てくる
形は似ている
expression_list ::= expression ("," expression)* [","] starred_list ::= starred_item ("," starred_item)* [","] starred_expression ::= expression | (starred_item ",")* [starred_item] starred_item ::= expression | "*" or_expr
何かほかを探す
__format__()
を調べる?
str.formatの{}
には式は書けないから参考にならなさそう
PEP 498 – Literal String Interpolationもざっと見てみたけどそれっぽい説明がないなあ
PEP 502 – String Interpolation - Extended Discussionもな
わからん!
勢いあまってStackoverflowデビューした
python - What does a star (asterisk) do in f-string? - Stack Overflow
けっこうな勢いで反応があって驚いている
が、こうやって使うんだよという人は現れない
ドキュメントのミスか、あるいは将来の予約ってことかね
将来の予約ならPEPに書いてあってもよさそうなもの
ところでlambdaの扱いについて
f_expression
にはlambda_expr
は含まれないみたいな定義だけど
lambdaが書けるっていう記事も出てくる
どういうことか
lambda_expr
の定義はこう
lambda_expr ::= "lambda" [parameter_list] ":" expression
ああ
つまりこうは書けないけど
>>> f"{lambda x: x + 1}"
File "<fstring>", line 1
(lambda x)
^
SyntaxError: unexpected EOF while parsing
これなら書けるってことね
>>> f"{(lambda x: x + 1)(2)}"
'3'
こっちはlambda_expr
と見せかけてcall
だから、ってことでいいかな
call ::= primary "(" [argument_list [","] | comprehension] ")"
同じ意味でもこれなら書ける
>>> def add1(x): return x + 1
...
>>> f"{add1}"
'<function add1 at 0x019EF810>'
これと同じ結果になってもいいわけだけど
できなくても別に困ることはなさそう
(ってPEPに書いてあったことを後になって発見)