辞書を走査
このレッスンで作るもの — 辞書のキーと値を
items()で全部取り出し、キー = 値の形に並べた文字列を組み立てます。
辞書を走査する
前回は辞書を組み立てました。今度は中身を最初から最後までたどります。この「全部を順番に見る」ことを 走査 と呼びます。
辞書をそのまま for に渡すと、取れるのは キーだけ です。
record = {"name": "りんご", "price": 120, "category": "食費"}
for key in record:
print(key)表示は name、price、category の 3 行です。値がほしければ record[key] と書いて取りに行きます。動きますが、毎回取りに行くのは手間です。
items でキーと値を同時に取る
record.items() を使うと、キーと値の組が順番に取れます。for の変数を 2 つ書くのがポイントです。
record = {"name": "りんご", "price": 120, "category": "食費"}
for key, value in record.items():
print(key, value)1 周目は key が "name" で value が "りんご"、2 周目は "price" と 120、3 周目は "category" と "食費" になります。第 5 章の enumerate や zip と同じ、変数を 2 つ並べる書き方です。
items()の()を忘れてrecord.itemsと書くと、走査ではなくメソッドそのものを指してしまい、forの中で意図しない動きになります。かっこまでが名前だと思って書きます。
キーだけほしいときは record.keys()、値だけほしいときは record.values() もあります。3 つの使い分けは下記のとおりです。
並ぶ順番は決まっている
辞書は「順番を持たない」と説明されることがありますが、いまの Python では 書いた順、入れた順 が保たれます。{"name": ..., "price": ..., "category": ...} と作った辞書を items() で回せば、必ず name、price、category の順です。
順番が保証されるおかげで、辞書から作った文字列は毎回同じ並びになります。テストで結果を比較できるのはこの性質のためです。
動きを追ってみる
{"name": "りんご", "price": 120} から name = りんご と price = 120 の 2 行を作る流れを追います。
- 空のリスト
linesを用意する - 1 周目で
keyが"name"、valueが"りんご"になり、"name = りんご"をappendする - 2 周目で
"price = 120"をappendする "\n".join(lines)で 2 行を改行でつなぐ
def record_lines(record):
lines = []
for key, value in record.items():
lines.append(f"{key} = {value}")
return "\n".join(lines)f"{key} = {value}" は第 2 章の f-string です。value が 120 のような int でも、f-string の中では自動的に文字列として埋め込まれるので str() は要りません。
"\n".join(lines) は「リストの各要素を改行でつなぐ」という意味です。要素が 1 つなら改行は入らず、空リストなら空文字 "" が返ります。末尾に余計な改行が付かないのが join の便利なところです。
joinは「区切り文字.join(リスト)」の順で書きます。lines.join("\n")は逆で、エラーになります。つなぐ側が主語だと覚えます。
よくある間違い
for key, value in recordと書く —items()を付けずに 2 つ受け取ろうとするとValueErrorになります。辞書をそのまま回すと 1 周ごとにキーが 1 つ返るだけなので、2 つに分けられません。+でつなぐときにintを混ぜる —key + " = " + valueはvalueが120だとTypeErrorです。f-string を使うかstr(value)で変換します。- 末尾に改行を足してしまう — ループの中で
+ "\n"を付けると最後の行にも改行が残ります。joinを使えばこの問題は起きません。
やってみよう
関数 record_lines(record) を実装してください。辞書 record を items() で走査し、1 組ごとに キー = 値 という 1 行を作って、改行 \n でつないだ文字列を return します。
= の前後には半角スペースを 1 つずつ入れます。末尾に改行は付けません。空の辞書 {} を渡されたときは空文字 "" を返してください。キーの並びは辞書に入っている順のままにし、並べ替えはしません。
要件
- 関数名は record_lines で、引数は record の1つ
- items() でキーと値を同時に取り出して走査する
- 1行は「キー = 値」の形で、= の前後に半角スペースを1つずつ入れる
- 行の区切りは改行で、末尾には改行を付けない。空の辞書のときは空文字を返す
入出力例
record_lines({"category":"食費","name":"りんご","price":120}) → "name = りんご
price = 120
category = 食費"
record_lines({"name":"ノート","price":200}) → "name = ノート
price = 200"
record_lines({"price":0}) → "price = 0"
record_lines({}) → ""
record_lines({"category":"娯楽","name":"映画","price":1800}) → "category = 娯楽
name = 映画
price = 1800"