Python二维列表生成异常:为何所有子列表均为最后学生的考试信息
问题:生成学生考试列表时,所有子列表均为最后一位学生的信息?
存在元组列表exams_to_students,每个元组如(2,11)表示学生11需参加考试2。需生成二维列表,其中第i个子列表对应学生i的考试ID集合。
编写Python代码后,最终输出的二维列表中所有子列表均为最后一位学生的考试信息,但在examsEachStudentsIsDoing.append(exams)前添加打印语句,显示中间结果是正确的。
原代码
examsEachStudentsIsDoing = [] exams = [] number_of_students = 14 exams_to_students = [(0, 1), (0, 4), (0, 5), (0, 3), (0, 10), (0, 13), (0, 9), (0, 11), (0, 12), (0, 2), (0, 7), (0, 6), (1, 7), (2, 7), (2, 5), (2, 0), (2, 11), (2, 13), (3, 4), (4, 6), (4, 8)] for i in range(0,number_of_students): exams.clear() for j in range(0,len(exams_to_students)): if (exams_to_students[j][1]==i): exams.append(exams_to_students[j][0]) examsEachStudentsIsDoing.append(exams) print(examsEachStudentsIsDoing)
打印的中间结果
[2] [0] [0] [0] [0, 3] [0, 2] [0, 4] [0, 1, 2] [4] [0] [0] [0, 2] [0] [0, 2] [[0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2]]
原因分析
问题出在Python里的列表是可变对象:你只创建了一个exams列表,每次循环调用exams.clear()只是清空这个列表的元素,并没有生成新的列表。当你执行examsEachStudentsIsDoing.append(exams)时,添加的不是当前exams的副本,而是指向这个唯一列表的引用。
循环过程中,每次修改的都是同一个exams:清空后加入当前学生的考试ID,再把这个列表的引用塞进二维列表。等循环到最后一位学生时,exams被改成了最后一位的考试信息,而二维列表里所有元素都是指向这个列表的引用,所以最后打印时,所有子列表全是最后一次修改的结果。
中间打印结果正确是因为,每次append之前exams刚好被更新成当前学生的信息,此时打印的是它的当前状态,但后续循环会继续修改同一个列表。
修正方法
不要复用同一个exams列表,而是在每次循环中创建新的列表:
方法1:循环内新建列表
examsEachStudentsIsDoing = [] number_of_students = 14 exams_to_students = [(0, 1), (0, 4), (0, 5), (0, 3), (0, 10), (0, 13), (0, 9), (0, 11), (0, 12), (0, 2), (0, 7), (0, 6), (1, 7), (2, 7), (2, 5), (2, 0), (2, 11), (2, 13), (3, 4), (4, 6), (4, 8)] for i in range(number_of_students): exams = [] # 每次循环新建一个独立列表 for exam_id, student_id in exams_to_students: if student_id == i: exams.append(exam_id) examsEachStudentsIsDoing.append(exams) print(examsEachStudentsIsDoing)
方法2:用列表推导式简化
number_of_students = 14 exams_to_students = [(0, 1), (0, 4), (0, 5), (0, 3), (0, 10), (0, 13), (0, 9), (0, 11), (0, 12), (0, 2), (0, 7), (0, 6), (1, 7), (2, 7), (2, 5), (2, 0), (2, 11), (2, 13), (3, 4), (4, 6), (4, 8)] examsEachStudentsIsDoing = [ [exam_id for exam_id, student_id in exams_to_students if student_id == i] for i in range(number_of_students) ] print(examsEachStudentsIsDoing)
内容的提问来源于stack exchange,提问作者SomethingNormal123
相关产品推荐
相关产品推荐

