こんにちは、久しぶりに記事を書く六角レンチです。
Copilot無料版で使ってますがすごい優秀なので楽しいです
問題のコード(関数)
とりあえずこのコードを見てほしい
def flat_3d_to_2d(input_data: list[list[list[float]]]) -> list[list[float]]:
return [[i for row in data for i in row] for data in input_data]
3次元のリストを2次元のリストに展開する感じの関数を書こうとdef flat_3d_to_2d
まで書いたら残りをCopilot君が全部書いてくれた
なにこれ????????
for文のあとにfor文が続く??
この関数の特に意味不明なポイントはリスト内包表記の部分
(型ヒントがでかすぎるのは気にしない)
[i for row in data for i in row]
普通のリスト内包表記であれば
[変数 for 変数 in イテラブル]
って感じで使われるものの左に使うものがある
三項演算子も
真の時の値 if 条件式 else 負の時の値
って感じで(真の時が普通だと考えれば)左にある感じ
なのにこの関数のfor文は二つもあって使うもの使われるものより左にある。
左に流れていくイメージがあるのでなんか違和感がすごい
公式ドキュメントを読んでみよう
上のpython公式ドキュメントのリスト内包表記の部分を見ると、下のように書いてある。
リスト内包表記は、括弧の中の 式、 for 句、そして0個以上の for か if 句で構成されます。 リスト内包表記の実行結果は、 for と if 句のコンテキスト中で式を評価した結果からなる新しいリストです。 例えば、次のリスト内包表記は2つのリストの要素から、違うもの同士をペアにします。
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
これは次のコードと等価です:
combs = [] for x in [1,2,3]: for y in [3,1,4]: if x != y: combs.append((x, y))
for と if 文が両方のコードで同じ順序になっていることに注目してください。
if文が一番後ろに付くのずっと違和感あったけどそういう理由あったんだな...
これをもとに考えてみると
[i for row in data for i in row]
は
a = []
for row in data:
for i in row:
a.append(i)
ということになる
結論
見た目はすっきりするしリスト内包表記だから多分普通に書くより速くなると思うけど可読性がゴミあまりよくないしわかる人が少なそうなので使わない方が無難かもしれない
後ろじゃなくて前に足していけばわかりやすくて使いたくなるんだけどな...