answer13_1.py

import csv

# 入力ファイルを開く
with open("scores_in.csv", "r", encoding="utf-8", newline="") as infile:
    reader_obj = csv.reader(infile)
    header = next(reader_obj)
    # ヘッダのフィールド数から科目数を求める
    num_courses = len(header) - 1
    # 科目ごとの合計点を求めるために初期化を行う
    course_total = [0] * num_courses
    # 出力ファイルを開く
    with open("scores_out.csv", "w", encoding="utf-8", newline="") as outfile:
        writer_obj = csv.writer(outfile)
        # 入力ファイルのヘッダ行を流用し、合計フィールドを追加する
        writer_obj.writerow(header+["合計"])
        num_students = 0
        for student_record in reader_obj:
            # この生徒の各科目の点数を整数のリストにする
            scores = [int(score) for score in student_record[-num_courses:]]
            # 合計点を求める
            total_score = sum(scores)
            # 合計点を求めて出力ファイルにレコードとして書く
            writer_obj.writerow(student_record+[total_score])
            # この生徒の各科目の点数を、科目ごとの合計点に足し込む
            course_total = [sum(pair) for pair in zip(course_total, scores)]
            num_students += 1
        # 科目ごとの平均点を求めて出力ファイルにレコードとして書く
        course_average = [round(each_total/num_students, 1) for each_total in course_total]
        writer_obj.writerow(["平均"]+course_average+[""])

# 章末問題 13章【1】解答例
#
# 入力ファイルscores_in.csvを読みながら出力ファイルscores_out.csvを
# 書くために、with文(4行目)で入力ファイルを開いた状態でwith文(12行目)で
# 出力ファイルを開いて、その本体でファイルを読み書きしています。
#
# 入力ファイルからの読み込みは、ヘッダについては6行目のnextで、
# 内容については17行目のfor文で、いずれもreader_objをイテレータとして
# 使うことで行っています。
#
# 出力ファイルへの書き出しは、ヘッダについては15行目、各生徒のデータに
# ついては23行目、科目ごとの平均点については28行目で、いずれもwriterow
# メソッドを用いて行っています。
#
# 19行目の内包表記は、student_recordの後ろnum_courses(科目数)個の
# データをそれぞれ整数に変換して、その全体をリストにするという処理です。
#
# 25行目の内包表記は、科目ごとの合計点course_totalと、この生徒の得点
# scoresを、zipを使って組み合わせて、それぞれを足したものを集めて
# またリストにし、course_totalに代入し直すという処理です。例えば
# course_totalが[164, 149, 163]で、scoresが[68, 98, 71]なら、
# zipから得られるのは(164, 68)、(149, 98)、(163, 71)というタプルで、
# それぞれがpairに代入されるので、sum(pair)とすることでそれぞれの和
# 232、247、234を求め、これらがリストになってcourse_totalに代入されます。