コース進捗 コース目次 24レッスン中 24件を公開中
Pythonの基礎
データとコレクション
信頼できるプログラムを作る
オブジェクトでモデル化する
プロフェッショナルなPython
上級Python
ループには、一つの仕事
第7章では、リスト、辞書、集合という箱を作りました。今度はPythonが箱を一つずつ訪ねて、小さな仕事をします。
- 一つ取る Pythonが値を受け取る
- 仕事をする ループの中を実行
- 次へ進む 最後まで繰り返す
必要な値を、そのまま受け取りましょう。
topics = ["Python", "Git", "SQL"]
for topic in topics:
print("練習", topic)
表示用の番号も必要なら、enumerate()を使います。
for number, topic in enumerate(topics, start=1):
print(number, topic)
出力:
1 Python
2 Git
3 SQL
start=1が変えるのは、enumerate()が作る番号だけです。リストや本当のインデックスは変わりません。数値のインデックス自体が必要なときだけ、range(len(topics))を選びます。
zip()で二列を組にする
カードが二列に並んでいると想像してください。zip()は一枚目同士、二枚目同士をクリップで留めます。
- Python 55分
- Git 25分
- SQL 40分
topics = ["Python", "Git", "SQL"]
minutes = [55, 25, 40]
print(list(zip(topics, minutes)))
出力:
[('Python', 55), ('Git', 25), ('SQL', 40)]
大切な端があります。通常のzip()は、短い方が終わると止まります。
print(list(zip(["Python", "Git", "SQL"], [55, 25])))
出力:
[('Python', 55), ('Git', 25)]
SQLは何も言わず消えました。これが壊れたデータを意味するなら、zip(topics, minutes, strict=True)を使います。Python 3.10以降では、長さが違うとValueErrorになります。そのエラーの扱い方は第10章で学びます。
棚を崩さず並べ替える
sorted()は新しいリストを作ります。元のリストは、そのままです。
minutes = [55, 25, 40]
ranked = sorted(minutes, reverse=True)
print(ranked)
print(minutes)
出力:
[55, 40, 25]
[55, 25, 40]
レコードの一部分で比べたいときは、小さなkey関数を作ります。
def minutes_in(record):
return record["minutes"]
records = [
{"topic": "Python", "minutes": 40},
{"topic": "Git", "minutes": 25},
{"topic": "SQL", "minutes": 40},
]
print([record["topic"] for record in sorted(records, key=minutes_in, reverse=True)])
出力:
['Python', 'SQL', 'Git']
Pythonのソートは安定しています。PythonとSQLは同点なので、元の順番を保ちます。keyにはkey=minutes_inのように、()を付けず関数そのものを渡します。
短い注意:minutes.sort()はそのリストを変更し、Noneを返します。元の棚を残して新しい結果が欲しいなら、sorted(minutes)を使いましょう。
内包表記は、小さなコレクション工場
- 元のコレクション 20、35、50
- 必要なら絞る 30以上を残す
- 新しいコレクション 35、50
minutes = [20, 35, 50]
long_sessions = [value for value in minutes if value >= 30]
topic_names = {name.strip().casefold() for name in [" Python ", "python", "Git"]}
lookup = {topic: value for topic, value in zip(["Python", "Git"], [20, 35])}
print(long_sessions)
print(sorted(topic_names))
print(lookup)
出力:
[35, 50]
['git', 'python']
{'Python': 20, 'Git': 35}
角括弧ならリスト、式一つの波括弧なら集合、key: valueなら辞書です。読みやすい内包表記には、はっきりした変換が一つ、多くても単純な絞り込みが一つあります。判断や表示や更新がいくつも必要なら、普通のループへ広げます。短さより、読みやすさを選びましょう。
学習パレードを作る
次の完全なプログラムをstudy_parade.pyとして保存します。データを厳密に組にし、新しいリストを並べ替え、番号を付け、元データが変わらないことも確認します。
def make_records(topics, minutes):
return [
{"topic": topic, "minutes": duration}
for topic, duration in zip(topics, minutes, strict=True)
]
def minutes_in(record):
return record["minutes"]
def build_report(topics, minutes, target):
ranked = sorted(make_records(topics, minutes), key=minutes_in, reverse=True)
lines = []
for number, record in enumerate(ranked, start=1):
if record["minutes"] >= target:
status = "目標達成"
else:
status = "もう少し"
lines.append(
f"{number}. {record['topic']}:"
f"{record['minutes']}分({status})"
)
return lines
topics = ["Python", "Git", "SQL", "テスト"]
minutes = [55, 25, 40, 25]
topics_before = topics.copy()
report = build_report(topics, minutes, target=30)
assert topics == topics_before
assert report[0].startswith("1. Python")
print("学習パレード")
for line in report:
print(line)
print("元データ:", topics)
python3 study_parade.pyで実行します。
学習パレード
1. Python:55分(目標達成)
2. SQL:40分(目標達成)
3. Git:25分(もう少し)
4. テスト:25分(もう少し)
元データ: ['Python', 'Git', 'SQL', 'テスト']
Gitとテストは同点なので、安定ソートでGitが先のままです。AssertionErrorが出たら、約束した事実のどれかが崩れています。
3つの小さなチャレンジ
- 四つのおやつを、
enumerate(start=1)で番号付き表示にする。 - 三つの名前と二つの得点を通常の
zip()に渡し、次にstrict=Trueを追加してエラーの型を確認する。 - プロジェクトへ60分の記録を足し、目標を達成したテーマだけを内包表記で集める。
第9章へ進めるかな?
- 値を直接ループできる
-
enumerate()で人向けの番号を付けられる - 通常の
zip()が項目を落とす理由を説明できる - 元データを変えずに
sorted()を使える - 内包表記を単純に保ち、混み合ったらループを選べる
- 学習パレードを実行し、すべてのassertを通せた
次章では、これらの仕事を協力する小さな関数へ分け、それぞれの関数から名前が見える範囲を学びます。