0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🏫6時限目「f文字列・アンパック・リスト内包表記・joinとは?」【🍞Bakery Hubで学ぶPython・Webアプリ開発】

0
Last updated at Posted at 2026-09-16

3474.png

はじめに

普段は物流トラックドライバーをしながらPython学習をしている tosane932 です。

僕がPython学習を始めた初期から現在進行形で開発している、

🍞 sales_data_app 🥖

の実際のコードを教材に、Python基礎を学び直しています。

これまで、

1時限目
変数・データ型・比較演算子・if文

2時限目
リスト・辞書・set・for文

3時限目
関数・引数・return・関数の呼び出し・型ヒント

4時限目
モジュール・import・例外・try・except

5時限目
クラス・インスタンス・__init__・self・属性

と学び直してきました。

6時限目も、新しい教材を探すために別のコードを書くわけではありません。

すでに何度か見てきた app.py を、もう一度読んでみます。

現在の sales_data_app ではGuest Demoや店舗メモツールなど機能も増えていますが、今回もPython基礎に集中するため、AIアドバイスを作る処理の一部分だけを教材にします。

🐹「よし、じゃあ app.py の _generate_ai_advice() を開いてみよう📚️」

そこには、こんな1行があります。

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

🐹「……1行にいろいろ入りすぎでは?」

よく見ると、

f"{name}: {qty}個"

for name, qty in ranked_sales

[ ... for ... ]

", ".join(...)

と、まだ詳しく学んでいない書き方がいくつも入っています。

今回はこの1行を分解しながら、

f文字列・アンパック・リスト内包表記・join

について学び直していきます。


📚️ 今回の記事を3行でまとめると

  • f"{name}: {qty}個" から、変数を文字列へ埋め込むf文字列を確認する
  • for name, qty in ranked_sales から、複数の値を取り出すアンパックを確認する
  • リスト内包表記で作った文字列の一覧を、.join() で1つの文字列につなげる流れを実コードから追う

🍞 Guest Demoを公開しています

sales_data_app のGuest Demoを公開しています。

この記事で扱っている売上データやAIアドバイスを、実際の画面から確認できます。

https://bakery-salesdata.onrender.com/

Render上で公開しているため、初回アクセス時は画面が表示されるまで少し時間がかかる場合があります。


今回のコードはどこにある?

今回使うコードは、

sales_data_app
↓
app.py
↓
_generate_ai_advice()

の中にあります。

現在の関数は、Guest利用時の情報も扱えるように、

def _generate_ai_advice(ranked_sales, current_dataset=None):

という形になっています。

今回は、

ranked_sales

から sales_summary を作るPython基礎だけに集中するため、

current_dataset=None

については深入りしません。

今回読む実コードはこちらです。

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

3時限目では、このあとにある、

prompt = build_sales_prompt(sales_summary)

から、

sales_summaryを作る
↓
build_sales_prompt()へ渡す
↓
AIへ送るプロンプトを作る

という流れを見ました。

今回は、

sales_summary = ...

の右側で何をしているのか

をさらに細かく見ていきます。

🐹「前に通った場所だけど、まだ掘ってなかったところか。」


🍞 それでは6時限目

今回のテーマ

「f文字列・アンパック・リスト内包表記・joinとは?」

今回学び直すのは4つです。

📚 今回学ぶ4つ

  1. f文字列:文字列の中へ変数や値を埋め込む
  2. アンパック:まとまった複数の値を、それぞれの変数へ取り出す
  3. リスト内包表記:繰り返し処理を使ってリストを作る書き方
  4. join:複数の文字列を、区切り文字を使って1つにつなげる

今回のコードでは、

ranked_salesから値を取り出す
↓
nameとqtyへ分ける
↓
f文字列を作る
↓
リストにする
↓
joinで1つの文字列へつなぐ

という流れになっています。


1. 📝 f文字列とは?

まずは、この部分です。

f"{name}: {qty}個"

先頭に、

f

があります。

これは**f文字列(f-string)**と呼ばれる書き方です。

例えば、

name = "メロンパン"
qty = 12

という変数があるとします。

普通の文字列なら、

"メロンパン: 12個"

と直接書けます。

でも、商品名や販売数は毎回同じとは限りません。

そこで、

f"{name}: {qty}個"

と書くと、

{name}
↓
nameの中身

{qty}
↓
qtyの中身

が文字列へ入ります。

結果は、

メロンパン: 12個

です。

🐹「文字列の中に変数を差し込めるんだ。」


{}の中に値を書く

もう少し簡単な例なら、

bread = "あんぱん"
price = 180

message = f"{bread}は{price}円です"

と書けます。

message の中身は、

あんぱんは180円です

になります。

f"..."
↓
f文字列

{bread}
↓
変数breadの値を入れる

{price}
↓
変数priceの値を入れる

という形です。


🍞 sales_data_appでは?

今回の実コードでは、

f"{name}: {qty}個"

です。

例えば、

name = "メロンパン"
qty = 12

なら、

メロンパン: 12個

になります。

そして、

name = "あんぱん"
qty = 7

なら、

あんぱん: 7個

になります。

つまり、この部分では、

商品名と販売数を、AIへ渡しやすい文字列へ変えている

と読めます。

💡 qtyは数字なのに、なぜjoinできる?

qty は販売数なので、もともとは整数です。

例えば、

qty = 12

です。

しかし、

f"{name}: {qty}個"

というf文字列を作った時点で、

メロンパン: 12個

という文字列になります。

あとで使う .join() は文字列同士をつなぐ処理なので、

整数のqty
↓
f文字列の中へ入れる
↓
1つの文字列になる
↓
joinでつなげられる

という流れになっています。


2. 📦 アンパックとは?

次は、

for name, qty in ranked_sales

です。

2時限目では、

for

を使って、リストなどから値を1つずつ取り出す処理を見ました。

例えば、

breads = ["メロンパン", "あんぱん"]

for bread in breads:
    print(bread)

なら、

メロンパン
あんぱん

と1つずつ取り出せます。

でも今回のコードは、

for name, qty in ranked_sales

となっています。

変数が、

name
qty

と2つあります。

🐹「forの後ろに2人いる。」


ranked_salesはどこから来る?

ここで、実コードをもう少しだけ前へ戻ってみます。

AIアドバイスを呼び出す処理では、売上データから、

ranked_sales = sorted(
    sales_data.items(),
    key=lambda item: item[1],
    reverse=True,
)

という形で ranked_sales を作っています。

今回は sorted() や lambda を詳しく学ぶ回ではないため、ここでは、

商品名と販売数を、販売数の大きい順に並べている

くらいに読んで進みます。

🐹「また知らない lambda がいるけど、今日は追いかけない。」

注目したいのは、

sales_data.items()

です。

辞書の .items() では、

キー
値

を1組ずつ取り出せます。

例えば、

sales_data = {
    "メロンパン": 12,
    "あんぱん": 7,
}

なら、

("メロンパン", 12)
("あんぱん", 7)

のような組み合わせとして扱えます。

そのため ranked_sales も、イメージとしては、

[
    ("メロンパン", 12),
    ("あんぱん", 7),
]

のような、

商品名
販売数

の組み合わせになります。


ここでタプルが出てくる

("メロンパン", 12)

のように、

商品名
販売数

が2つで1組になっています。

この、

("メロンパン", 12)

のようなデータはタプルです。

💡 タプルは今回は深入りしません

("メロンパン", 12) のように、複数の値を1組にしたデータはタプルです。

今回は、

商品名と販売数が2つで1組になっている

くらいのイメージで進めます。

タプル自体は、また必要になったときに改めて掘ります。


2つの値を2つの変数へ取り出す

例えば、

name, qty = ("メロンパン", 12)

とすると、

name
↓
"メロンパン"

qty
↓
12

と分かれます。

このように、

まとまっている複数の値を、それぞれの変数へ取り出す

ことを、今回はアンパックとして覚えます。

実コードの、

for name, qty in ranked_sales

でも同じです。

まず、

("メロンパン", 12)

を取り出して、

name = "メロンパン"
qty = 12

となります。

次に、

("あんぱん", 7)

を取り出して、

name = "あんぱん"
qty = 7

となります。

流れにすると、

ranked_sales

↓

("メロンパン", 12)

↓

name = "メロンパン"
qty = 12

↓

("あんぱん", 7)

↓

name = "あんぱん"
qty = 7

です。

🐹「2時限目のforが、2つずつ取り出す形になったんだ。」

💡 なぜ2つの変数で受け取れる?

今回の1件分は、

("メロンパン", 12)

のように2つの値を持っています。

そのため、

for name, qty in ranked_sales:

と、

name
qty

の2つへ分けて受け取れます。

今回は、

2つの値
↓
2つの変数

と対応している、と読めればOKです。


3. 🔁 リスト内包表記とは?

次は、この部分を見ます。

[f"{name}: {qty}個" for name, qty in ranked_sales]

🐹「カッコの中にforが入ってる。」

これはリスト内包表記と呼ばれる書き方です。

簡単な形なら、

[処理 for 値 in 繰り返すもの]

のように書けます。

例えば、

numbers = [1, 2, 3]

から、

[number * 2 for number in numbers]

とすると、

[2, 4, 6]

という新しいリストを作れます。


普通のfor文で書くと?

同じ処理を、これまで学んだ for を使って書くと、

result = []

for number in numbers:
    result.append(number * 2)

のように書けます。

結果は、

[2, 4, 6]

です。

リスト内包表記では、

[number * 2 for number in numbers]

と、短く書けます。

リスト内包表記は、

必ず短く書いた方が良い

というものではありません。

まずは、

forで値を取り出す
↓
処理する
↓
新しいリストを作る

という流れを読めることを目標にします。


🍞 sales_data_appのリスト内包表記

実コードへ戻ります。

[f"{name}: {qty}個" for name, qty in ranked_sales]

少し分けると、

for name, qty in ranked_sales
↓
商品名と販売数を取り出す

そして、

f"{name}: {qty}個"
↓
文字列を作る

となります。

ranked_sales が、

[
    ("メロンパン", 12),
    ("あんぱん", 7),
]

なら、

1回目は、

f"{name}: {qty}個"

から、

メロンパン: 12個

ができます。

2回目は、

あんぱん: 7個

ができます。

その結果、

[
    "メロンパン: 12個",
    "あんぱん: 7個",
]

という新しいリストになります。

🐹「元は商品名と数字だったのに、文字列のリストになった。」


普通のfor文へ戻してみる

今回のリスト内包表記を、

これまで学んだ形へ戻すと、イメージとしてはこうです。

sales_items = []

for name, qty in ranked_sales:
    sales_items.append(f"{name}: {qty}個")

すると、

sales_items

は、

[
    "メロンパン: 12個",
    "あんぱん: 7個",
]

になります。

今回の、

[f"{name}: {qty}個" for name, qty in ranked_sales]

は、この処理を短くまとめた形です。


4. 🔗 joinとは?

ここまでで、

[
    "メロンパン: 12個",
    "あんぱん: 7個",
]

というリストができました。

でも実コードは、まだ外側に続いています。

", ".join(...)

です。

join は、

複数の文字列を、1つの文字列につなげる

ときに使えます。


簡単な例

例えば、

breads = [
    "メロンパン",
    "あんぱん",
    "クロワッサン",
]

があるとします。

これを、

", ".join(breads)

とすると、

メロンパン, あんぱん, クロワッサン

という1つの文字列になります。

ここで、

", "

が、文字列と文字列の間に入っています。

メロンパン
+
", "
+
あんぱん
+
", "
+
クロワッサン

というイメージです。


joinは区切り文字側に書く

最初に見ると少し不思議なのが、

", ".join(breads)

という順番です。

", "
↓
何を間に入れるか

.join(...)

↓

中の文字列をつなげる

となります。

つまり、

", ".join(...)

なら、

カンマ+半角スペースでつなぐ

という意味になります。

💡 joinがつなぐのは文字列

例えば、

["メロンパン", "あんぱん"]

のような文字列の集まりなら、そのまま join できます。

一方で、

[12, 7]

のように整数がそのまま入っているリストは、今回のようには join できません。

sales_data_app では先に、

f"{name}: {qty}個"

で文字列へ変えているため、

そのあと join でつなげられます。


🍞 sales_data_appでは?

今回のコードでは、

", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

です。

内側では、

[
    "メロンパン: 12個",
    "あんぱん: 7個",
]

というリストを作ります。

それを、

", ".join(...)

すると、

メロンパン: 12個, あんぱん: 7個

という1つの文字列になります。

そして、

sales_summary = ...

によって、

sales_summary

へ代入されます。


🔗 4つを全部つなげてみる

今回の実コードを、もう一度見てみます。

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

最初はかなり詰まって見えます。

でも、こういうコードは一番内側から外側へ読むと追いやすくなります。

ranked_sales

↓

("メロンパン", 12)
("あんぱん", 7)

↓

for name, qty in ranked_sales

↓

nameとqtyへアンパックする

↓

f"{name}: {qty}個"

↓

"メロンパン: 12個"
"あんぱん: 7個"

↓

リスト内包表記でリストにする

↓

[
    "メロンパン: 12個",
    "あんぱん: 7個",
]

↓

", ".join(...)

↓

"メロンパン: 12個, あんぱん: 7個"

↓

sales_summaryへ代入

となります。

🐹「1行だけど、中では結構働いてる。」


これまでの書き方へ戻すと?

今回の1行を、

これまで学んだ for を使って少し長く書くと、

sales_items = []

for name, qty in ranked_sales:
    sales_items.append(f"{name}: {qty}個")

sales_summary = ", ".join(sales_items)

というイメージになります。

そして実コードでは、

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

とまとめています。

短く書かれていても、

for
↓
値を取り出す

アンパック
↓
nameとqtyへ分ける

f文字列
↓
文字列を作る

リスト内包表記
↓
新しいリストを作る

join
↓
1つの文字列につなげる

と分解すると、これまで学んだ基礎とつながって見えてきます。


🤖 作った文字列はどこへ行く?

ここで作った、

sales_summary

は、そのまま終わるわけではありません。

すぐ後ろで、

prompt = build_sales_prompt(sales_summary)

と使われています。

3時限目で見た、

build_sales_prompt(...)

です。

流れにすると、

sales_data
↓
商品名と販売数の組み合わせを作る
↓
販売数の大きい順にranked_salesへ並べる
↓
nameとqtyへアンパックする
↓
f文字列へ変換する
↓
joinで1つにまとめる
↓
sales_summary
↓
build_sales_prompt(sales_summary)
↓
AIへ渡すプロンプトを作る

となります。

例えば、

メロンパン: 12個, あんぱん: 7個

という文字列が作られ、

AIが売上データを読める形へつながっていきます。

🐹「Pythonの書き方を勉強してたら、最後はちゃんと画面のAIにつながった。」


🍞 今回の処理をGuest Demoで確認できます

今回扱った、

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

は、AIアドバイスを作る処理の中で実際に使われています。

画面上では、

売上データを見る
↓
AIアドバイスを生成する

という操作ですが、その裏側では、

売上データを集める
↓
商品名と販売数を組み合わせる
↓
販売数の大きい順に並べる
↓
文字列へ変換する
↓
1つの売上要約へまとめる
↓
AI用プロンプトへ渡す

という処理が動いています。

https://bakery-salesdata.onrender.com/


📝 6時限目まとめ

今回は、app.py の _generate_ai_advice() にある実コードから、

f文字列

文字列の中へ変数などの値を埋め込む。

f"{name}: {qty}個"

アンパック

まとまった複数の値を、それぞれの変数へ取り出す。

for name, qty in ranked_sales

リスト内包表記

繰り返しながら、新しいリストを作る書き方。

[f"{name}: {qty}個" for name, qty in ranked_sales]

join

複数の文字列を1つにつなげる。

", ".join(...)

を学び直しました。

実コードでは、

ranked_sales
↓
nameとqtyへアンパック
↓
f文字列を作る
↓
リスト内包表記でリストにする
↓
joinで1つにつなげる
↓
sales_summaryへ代入する

と、1本につながっています。


🤔 自分で確認してみる

最後に、今回の内容を自分でも確認してみます。

Q1

次のコードの先頭にある f は何のためにあるでしょう?

f"{name}: {qty}個"
A. for文を開始する
B. 文字列の中へ値を埋め込む
C. 関数を定義する
🅰️答えを見る

B. 文字列の中へ値を埋め込む

です。

例えば、

name = "メロンパン"
qty = 12

なら、

メロンパン: 12個

になります。


Q2

次のコードでは、

for name, qty in ranked_sales

なぜ変数が2つあるのでしょう?

🅰️答えを見る

今回の ranked_sales では、

("メロンパン", 12)

のように、商品名と販売数が2つで1組になっています。

それを、

name
qty

へそれぞれ取り出しているためです。


Q3

次のコードは何を作るでしょう?

[f"{name}: {qty}個" for name, qty in ranked_sales]

ranked_sales は、

[
    ("メロンパン", 12),
    ("あんぱん", 7),
]

とします。

🅰️答えを見る
[
    "メロンパン: 12個",
    "あんぱん: 7個",
]

という新しいリストを作ります。


Q4

次の、

", ".join(...)

の、

", "

は何を表しているでしょう?

🅰️答えを見る

文字列同士をつなぐときに使う、

区切り文字

です。

今回なら、

メロンパン: 12個, あんぱん: 7個

のように、

カンマ + 半角スペース

が間に入ります。


Q5

次の実コード全体では、最後にどのような値ができますか?

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

ranked_sales は、

[
    ("メロンパン", 12),
    ("あんぱん", 7),
]

とします。

🅰️答えを見る
メロンパン: 12個, あんぱん: 7個

という1つの文字列が作られ、

sales_summary

へ入ります。


Q6

次の2つは、今回の範囲ではどんな関係でしょう?

sales_items = []

for name, qty in ranked_sales:
    sales_items.append(f"{name}: {qty}個")

そして、

[f"{name}: {qty}個" for name, qty in ranked_sales]
🅰️答えを見る

どちらも、

ranked_salesから
nameとqtyを取り出す
↓
f文字列を作る
↓
新しいリストを作る

という処理です。

下のコードは、

リスト内包表記

を使って短く書いています。


Q7

今回の処理で、

qty = 12

のような整数が含まれているのに、

", ".join(...)

を使えるのはなぜでしょう?

🅰️答えを見る

先に、

f"{name}: {qty}個"

というf文字列を作っているからです。

qty = 12
↓
f文字列の中へ入る
↓
"メロンパン: 12個"
↓
文字列になる
↓
joinでつなげられる

という流れです。


🐹 6時限目を終えて

今回は、

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

という、たった1つの実コードを教材にしました。

最初に見ると、

🐹「カッコの中にforがいて、その外にjoinまでいる。」

となります。

でも分解すると、

f文字列
↓
値を文字列へ入れる


アンパック
↓
2つの値をnameとqtyへ分ける


リスト内包表記
↓
繰り返しながらリストを作る


join
↓
複数の文字列を1つにつなげる

という、それぞれの役割を見ることができました。

さらに今回は、その1行だけではなく、

ranked_sales = sorted(
    sales_data.items(),
    key=lambda item: item[1],
    reverse=True,
)

まで少しだけ前へ戻りました。

すると、

sales_data
↓
辞書のitems()から
商品名と販売数を取り出す
↓
ranked_sales
↓
nameとqtyへアンパック

という流れまでつながりました。

そして今回も、

2時限目で学んだ、

for

や、

1時限目から何度も使っている、

=

による代入が出てきました。

さらに完成した、

sales_summary

は、

3時限目で見た、

build_sales_prompt(sales_summary)

へつながっています。

以前学んだコード
↓
もう一度見る
↓
前は気にしなかった書き方を見つける
↓
さらに分解する
↓
前の基礎ともつながる

今回もこの繰り返しです。

🐹「1行だけでも、掘る場所は結構ある。」

もちろん今回も、記事を1本書いただけで、

「リスト内包表記を完全に理解した!」

とは考えません。

これからコードを読んでいて、

f"..."

を見つけたら、

何の値を文字列へ入れているんだろう?

と考える。

for a, b in ...

を見つけたら、

何を2つに分けているんだろう?

と考える。

[... for ...]

を見つけたら、

何を繰り返して、
どんなリストを作っているんだろう?

と考える。

.join(...)

を見つけたら、

何を、どんな区切りでつないでいるんだろう?

と考える。

そんな読み方が少しずつできれば、

以前なら、

sales_summary = ", ".join(
    [f"{name}: {qty}個" for name, qty in ranked_sales]
)

を、

「なんか難しそうな1行」

として通り過ぎていたところも、

少しずつ中身が見えるようになりそうです。

そして今回、途中で出てきた、

("メロンパン", 12)

というタプルも、まだ詳しく学んでいません。

さらに、

key=lambda item: item[1]

というlambdaも出てきました。

🐹「また次に調べられそうなものが増えた。」

全部を一度に覚えようとせず、

必要になったところから一つずつ掘っていきます。

まだまだPython基礎の学び直しは続きます。

次の時限も、🍞 sales_data_app の実コードを教材にして読んでいきます🐹


📚️ 基礎学習シリーズ

🏫1時限目

「変数・データ型・比較演算子・if文とは?」

🏫2時限目

「リスト・辞書・set・for文とは?」

🏫3時限目

「関数・引数・return・関数の呼び出し・型ヒントとは?」

🏫4時限目

「モジュール・import・例外・try・exceptとは?」

🏫5時限目

「クラス・インスタンス・init・self・属性とは?」

🏫6時限目

「f文字列・アンパック・リスト内包表記・joinとは?」

🏫7時限目

「strip・len・splitlines・スライスとは?」

🏫8時限目

「None・is・is not・isinstanceとは?」

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?