students = ['Alice', 'Bob', 'Charlie']
subjects = ['Math', 'Science', 'English']
all_grades = [
    [85, 90, 88],  # Alice
    [78, 83, 82],  # Bob
    [92, 88, 91]   # Charlie
]
grades = {student: {subject: grade for subject, grade in zip(subjects, grades)} for student, grades in zip(students, all_grades)}
print(grades)
唯一想問的是 grades 這條變數裡面的字典生成式是怎麼跑的@@?看了整個霧煞煞。
這段程式碼使用了字典生成式(dictionary comprehension)來生成一個嵌套的字典,包含每個學生在每個科目的成績。
grades = {student: {subject: grade for subject, grade in zip(subjects, grades)} for student, grades in zip(students, all_grades)}
這段程式碼其實分為兩層的字典生成式:
zip 函數zip(subjects, grades)
zip(subjects, grades) 會把 subjects 和 grades 這兩個列表「配對」起來。例如,對於 Alice 來說:
subjects 是 ['Math', 'Science', 'English']
grades 是 [85, 90, 88]
zip(subjects, grades) 就會生成一個類似於 [('Math', 85), ('Science', 90), ('English', 88)] 的配對。
{subject: grade for subject, grade in zip(subjects, grades)}
這個生成式會對 zip(subjects, grades) 的每一對 (subject, grade) 生成一個字典條目。對於 Alice:
'Math': 85
'Science': 90
'English': 88
這樣,內層字典就會變成 {'Math': 85, 'Science': 90, 'English': 88}。
{student: {subject: grade for subject, grade in zip(subjects, grades)} for student, grades in zip(students, all_grades)}
這裡的 zip(students, all_grades) 會把 students 和 all_grades 配對起來:
('Alice', [85, 90, 88])
('Bob', [78, 83, 82])
('Charlie', [92, 88, 91])
然後,對於每一對 (student, grades),外層字典生成式會以 student 為鍵,並將內層字典(每個科目的成績)作為對應的值。最終生成的 grades 字典如下:
{
    'Alice': {'Math': 85, 'Science': 90, 'English': 88},
    'Bob': {'Math': 78, 'Science': 83, 'English': 82},
    'Charlie': {'Math': 92, 'Science': 88, 'English': 91}
}
用一般的 For 迴圈來寫,會長這樣:
grade_v1 = dict()
for student, grades in zip(students, all_grades):
    grade_v1[student] = dict()
    for subject, grade in zip(subjects, grades):
        grade_v1[student][subject] = grade
print(grade_v1)
其中,第二層迴圈可以用單行寫法 aka Comprehensions 來簡化:
grade_v1[student] = dict()
for subject, grade in zip(subjects, grades):
    grade_v1[student][subject] = grade
# 等同於
grade_v1[student] = {subject: grade for subject, grade in zip(subjects, grades)}
用同樣的方式來簡化最外層的迴圈,就會變成你看到的那樣了:
grade_v2 = {
    student: {subject: grade for subject, grade in zip(subjects, grades)}
    for student, grades in zip(students, all_grades)
}
comprehension 很像是一般迴圈的倒裝句, 你只要依序一層層把它變回一般的迴圈就很容易理解:
student_grades = {}
for student, grades in zip(students, all_grades):
    # 這會依序取得每一個學生的所有分數
    # 'Alice' -> [85, 90, 88]
    # 'Bob' -> [78, 83, 82]
    # 'Charlie' -> [92, 88, 91]
    subject_grades = {}
    for subject, grade in zip(subjects, grades):
        # 這會依序取得
        # 'Math' -> 85
        # 'Science' -> 90
        # 'English' -> 88
        # 'Math' -> 78
        # 'Science' -> 83
        # 'English' -> 82
        # 'Math' -> 92
        # 'Science' -> 88
        # 'English' -> 91
        subject_grades[subject]=grade
    student_grades[student] = subject_grades
grades = student_grades
print(grades)