第 3 章获取高考原始成绩数据 ................................................................................................................ ———Python的字符串、列表、for循环、pandas和文件 本章使命 获取高考原始数据就是本章的使命。同时,通过本章的学习,能够了解 使用计算机生成模拟数据的思想和方法,并初步掌握Python中的字符串、列 表、for循环、pandas和CSV文件的读写方法。 3.1 Question——提出问题 要解决高考平行志愿录取问题的第一项工作就是对高考原始成绩进行赋分,而历年的 高考原始数据存储在各省教育厅,只有考生本人及有关投档高校才可以查阅,其他任何单位 或个人都无权查询成绩信息。我们似乎可以向省教育厅申请使用高考原始数据。但由于高 考数据涉及大量考生真实敏感信息,没有特殊需求,省教育厅一般不会向外提供。 我们如何用计算机模拟生成高考原始成绩数据呢? 3.2 What——探索问题本质 3.1 AI 助学 2. 我的问题:高考包括哪些成绩数据? 文心一言回答:高考成绩主要包括以下几方面的成绩数据。 统一高考科目成绩:包括语文、数学、外语三科的成绩。其中,语文和数学以原始分计 入总成绩,满分均为150 分。外语满分也为150 分,其中听力部分占30 分(部分省份听力成 绩不计入总分), 笔试部分占120 分。外语成绩通常是按照考生外语笔试成绩的1. 入总分,并按照四舍五入的原则取整。 25 倍计 选择科目成绩:是指考生根据本省的高考政策,从物理、历史、化学、生物学、思想政治、 地理等科目中自主选择的科目成绩。这些科目的成绩计入高考总分。具体计入方式根据各 第3章获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件55 省的高考政策而定,有的以原始分计入,有的以转换后的等级分计入,但每科满分通常为 100 分。 此外,高考还可能包括综合素质评价的成绩,这部分成绩主要考察学生的品德、思想政 治素质、实践能力、创新精神等方面。不过,综合素质评价的具体实施和成绩使用方式因地 区而异,需要参照当地的高考政策。 以上是关于高考成绩数据的基本构成,具体政策可能会因地区和年份的不同而有所差 异。如果您需要更详细的信息,建议参考当地教育部门或相关机构发布的高考政策文件。 借助AI 的帮助,我们对考生的高考成绩数据有了一个宏观的了解,即包括语文、数学 和外语三门科目成绩以及自主选择的三门科目(即选科)成绩。这与我们对某直辖市的高考 成绩的了解是一致的。 3.2 探索问题本质 2. 分析某直辖市的高考原始成绩数据,至少包括学生的基本数据和6门成绩数据,即准考 证号、考生姓名、语文成绩、数学成绩、英语成绩以及3门选考科目成绩。在不影响算法设计 的情况下,我们将问题简化,默认每位学生高考选考科目相同,都选择了地理、历史和政治参 与考试。因此,高考成绩相关数据包括考生的准考证号、考生姓名及6门科目成绩。 由于高考成绩真实与否并不影响高考平行志愿录取算法的设计与实现,在无法获得真 实高考原始数据的情况下,我们可以用计算机模拟生成考生准考证号、姓名和6门科目成绩 数据,这样就可以完成高考原始成绩的获取任务。 用计算机模拟的成绩数据要与真实数据具有相同的特性。高考成绩一般具有如下 特征: 数学、语文、英语成绩范围为0~150 分;其余三门选考科目成绩范围为0~100 分。 总成绩和各科成绩均符合正态分布。图3-1是某直辖市某年高考成绩分布图,由图可 知,真实的高考原始数据符合正态分布,即大部分考生的高考成绩在成绩平均值左右波动, 成绩特别高和特别低的考生数量很少。 图3- 1 某直辖市某年高考成绩分布图 至此,我们要模拟的高考原始成绩数据将与表3-1所示的数据类似。其中,我们规定了 准考证号的构成规则,即KS+5 位的考生序号,默认考生不超过99999 人。 56 Python程序设计基础———思维、认知与创新 表3-1 考生信息结构 准考证号姓名语文数学英语历史地理政治 KS00001 张珊109 120 114 78 82 90 KS00002 李思123 116 137 84 92 94 KS00003 王武133 129 132 83 85 78 … … … … … … … 因此,本章的任务就是用计算机模拟生成与表3-1类似的、符合高考成绩特征的高考原 始成绩数据,即需要设计生成数据的算法并用Python 语言实现,还要将生成的数据进行 存储。利 用“分治算法”思想,可以将模拟生成高考原始成绩数据这个任务划分成以下要解决 的两个子任务: (1)用Python模拟高考原始成绩数据,包括准考证号、考生姓名和6门成绩。 (2)将模拟生成的高考原始成绩数据存储到文件中。 3.3 How——拓展求解问题必备的知识和能力 使用Python语言模拟生成高考原始成绩,需要解决如下问题: (1)如何表示考生数据。 (2)如何模拟生成考生数据。 (3)如何保存模拟生成的考生数据。 3.3.1 如何用Python表示考生数据 考生的成绩数据包括准考证号、考生姓名和6门成绩。其中,准考证号、考生姓名是字 符串,6门成绩是整数。 3.3.1.1 用String类型表示字符串 Python中的String是一种用于表示字符串的数据类型,准考证号和考生姓名等一串字 符类型的信息就可以用String类型来表示。 1.定义字符串 字符串是由零个或多个字符组成的序列。Python中的字符串可以写在一对单引号、双 引号或三引号中。 【例3-1】 使用String类型保存字符串型数据。 1 s1="Hello World!" 2 s2='你好,世界!' 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 57 3 s3="It's a cat" #如果把's 换成"会怎样呢? 4 s4='It"s a dog' #如果把"s 换成'会怎样呢? 5 s5='同学你好,\n 欢迎学习Python!' 6 s6= ''' 7 同学你好, 8 欢迎学习Python! 9 ''' 10 print(s1) #输出:Hello World! 11 print(s2) #输出:你好,世界! 12 print(s3) #输出:It's a cat 13 print(s4) #输出:It"s a dog 14 print(s5) 15 print(s6) 在上面的代码中: 第1行定义了一个字符串变量s1,其值为由两个双引号“""”括起来的字符串“hello world!”。 第2行定义了一个字符串变量s2,其值为由两个单引号“' '”括起来的字符串‘你好, 世界!’。 第3行和第4行定义了两个字符串变量s3和s4,s3和s4中保存的字符串有一个共同 特点,就是字符串本身已经包含一个单独的单引号或双引号,所以包含这个字符串的引号必 须与字符串内的引号相区分,不能同时使用一种引号格式。即字符串内的单个引号如果是 单引号,字符串外的那对引号就只能是双引号;如果字符串内的单个引号是双引号,字符串 外的那对引号就只能是单引号。这样,程序才能正确识别字符串,否则程序就会报错。 第5行代码定义了一个字符串变量s5,其值为一个字符串,但这个字符串内部包含一 个特殊字符‘\n’,这个字符在Python中是转义字符,含义是换行,即输出字符串“同学你 好,”之后会输出一个换行符,然后在新的一行继续输出字符串“欢迎学习Python!”。第3 行和第4行代码中的问题也可以使用转义字符“\'”代表单引号或使用“\"”代表双引号解 决。即可将代码修改成s3="It\"sacat",s4=I't\s' adog',程序同样可以正确运行。什么 是转义字符? Python中还有哪些转义字符? 有兴趣的读者可以自行查阅。 第6~9行代码定义了一个字符串变量s6,其值用一对三引号括起来,一对三引号括起 来的字符串输出时会按照多行字符串的原样输出。 图3-2 例3-1运行结果 程序的运行结果如图3-2所示。 现在,我们已经可以用String类型表示考生数据中的准考证 号和考生姓名了。 2.访问字符串 Python中通过“字符串变量名[下标]”的形式访问字符串中 的某个字符。下标是指某个字符在字符串中的位置,既可以从前 往后数每个字符的位置,也可以从后往前数每个字符的位置。注 意,从前往后数时,下标从0开始数,依次增加1;从后往前数时, 下标从-1开始,依次减少1。 例如,字符串“我喜欢学习Python!”每个字符的下标如表3-2所示。 58 Python程序设计基础———思维、认知与创新 表3-2 字符串中的下标 字 符 串我喜欢学习P y t h o n ! 从前往后数,下标取值0 1 2 3 4 5 6 7 8 9 10 11 从后往前数,下标取值-12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 字符串的截取可以通过在字符串后添加“[下标开始位置:下标结束位置]”的形式截取 指定范围内的字符串,得到子串。 【例3-2】 访问字符串中的部分字符。 1 s='我喜欢学习Python!' 2 print(s[3:5]) #截取从下标3 开始到下标5 之前,即4 结束 3 print(s[-7:-1]) #截取从下标-7 开始,到-1 之前结束,即-2 结束 4 print(s[5:-1]) #截取从下标5 开始,到-1 之前结束,即-2 结束 5 print(s[:11]) #截取从下标0 开始,到11 之前结束,即10 结束 6 print(s[-7:]) #截取从下标-7 开始,到最后一个字符结束 7 print(s[:]) #截取全部字符 8 print(s[3]) #截取一个字符,下标为3 在上面的代码中: 第1行代码定义了一个字符串变量s1,其值为“我喜欢学习Python!”。 第2行代码打印截取的字符串子串,截取位置从下标3开始,至下标5之前结束,所以 截取的是下标为3和4的字符串子串,即“学习”。 第3行代码打印截取的字符串子串,截取位置从下标-7开始,至下标-1之前结束,所 以截取的是下标为-7、-6、……、-2的字符串子串,即“Python”。 第4行代码打印截取的字符串子串,截取位置从下标5开始,至下标-1之前结束,所 以截取的是下标为5、6、……、10(-2)的字符串子串,即“Python”。 第5行代码打印截取的字符串子串,下标开始位置省略,代表截取从下标0开始,至下 标11之前结束,所以截取的是下标为0、1、……、10 的字符串子串,即“我喜欢学习 Python”。 第6行代码打印截取的字符串子串,下标结束位置省略,代表截取到最后一个字符,并 且包含最后一个字符,所以截取的是下标为-7、-6、……、-1 的字符串子串,即 “Python!”。 第7行代码打印截取的字符串子串,截取开始位置和结束位置都省略,代表截取全部字 符,即“我喜欢学习Python!”。 第8行代码打印截取的字符串中的某单个字符,下标位置为3,所以结果为“学”。 图3-3 例3-2运行结果 程序运行结果如图3-3所示。 3.操作字符串 1)常用操作 Python字符串的基本操作包括字符串拼接、字符串重复和判断 是否是子串等。我们可以使用加号(+)对字符串进行拼接、使用乘 号(*)对字符串进行重复、使用保留字(in或notin)判断一个字符 串是否是另一个字符串的子串。 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 59 【例3-3】 字符串的+、*、in或notin操作方法示例。 1 str1 = 'Hello' 2 str2 = ' World' 3 str3 = str1 + str2 #拼接字符串 4 print(str3) #输出:Hello World 5 str4 = 'Hello' 6 str5 = str4 * 3 #重复字符串 7 print(str5) #输出:HelloHelloHello 8 s1 = '我喜欢学习Python!' 9 s2 = 'Python' 10 s3 = 'C++' 11 print(s2 in s1) 12 print(s3 in s1) 13 print(s3 not in s1) 在上面的代码中: 第1行定义了一个字符串变量str1,其值为“Helllo”。 第2行定义了一个字符串变量str2,其值为“World”。 第3行使用+将字符串str1和str2拼接成一个字符串,并赋值给str3。 第4行打印输出拼接后的字符串str3。 第5行定义了一个字符串变量str4,其值同样为“Helllo”。 第6行使用*将str4字符串重复三次生成一个新的字符串,并赋值给str5。 第7行打印输出重复后的字符串str5。 第8行定义了一个字符串变量s1,其值为“我喜欢学习Python!”。 第9行定义了一个字符串变量s2,其值为“Python”。 第10行定义了一个字符串变量s3,其值为“C++”。 第11行使用in保留字判断s2是否是s1的子串,并将判断结果输出。 第12行使用in保留字判断s3是否是s1的子串,并将判断结果输出。 第13行使用notin保留字判断s3是否不是s1的子串,并将判断结果输出。 图3-4 例3-3运行结果 程序运行结果如图3-4所示。 第11行、12行、13行的输出结果分别为True、False、True,分 别表示s2是s1的子串,s3不是s1的子串,s3不是s1的子串。 Python标准库中提供了许多操作字符串的方法,比如将其他 数据类型转换为字符串的str函数(方法);填充字符串至指定长度 的zfill函数;求字符串长度的len函数;将英文单词首字母转为大 写的title函数;将英文字母转为大写的upper函数;将英文字母转为小写的lower函数;去 除字符串两端空白的strip函数;字符串替换replace函数;字符串分割的split函数;将字符 串格式化的format函数等。有需求或感兴趣的读者可以查阅官方文档获取更多用法,下面 仅介绍str方法和zfill方法的具体使用方法。 2)str方法与type函数 str方法用于将各种类型的数据转换为字符串类型。例如,可以将数字转换成字符串, 也可以将列表转换为字符串。Python中提供的type函数用于查看数据的类型。 60 Python程序设计基础———思维、认知与创新 【例3-4】 str方法和type方法的使用。 1 x=123 2 print(x) 3 print(type(x)) #输出变量x 的数据类型 4 s1 = str(123) #将数字123 转变为字符串"123" 5 print(s1) #输出转化后的变量s1 6 print(type(s1)) #输出变量s1 的数据类型 7 ls=[1,2,3] 8 s2=str(ls) #将列表[1,2,3]转变为字符串"[1,2,3]" 9 print(s2) #输出转化后的变量s2 10 print(type(s2)) #输出变量s2 的数据类型 程序运行结果如图3-5所示。 3)zfill方法 zfill方法的功能是在字符串左侧添加若干“0”字符,以达到指定长度。 具体语法: str.zfill(width) 其中,str为要填充的字符串,width为指定的字符串长度。 【例3-5】 参考表3-1准考证号的格式,前两位为“KS”,后5位为考生的序号。使用 zfill方法生成准考证号。 1 #生成指定长度的字符串 2 no1 = '1' 3 #把字符1 左侧拼接4 个0 返回;'KS'与返回字符串拼接成一个新字符串 4 s_no1 = 'KS'+no1.zfill(5) 5 print(s_no1) 程序运行结果如图3-6所示。 图3-5 例3-4运行结果图3-6 例3-5运行结果 关于String类型,可扫描二维码学习更多细节。 3.3.1.2 用列表表示考生的数据 在例2-13中我们已经知道可以使用列表这种数据类型来表示多项信息。那么,Python 中列表具体是什么样的数据类型? 准考证号和考生姓名也可以放在列表里吗? 如何定义和 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 61 访问列表? 列表有哪些常用的方法呢? 接下来介绍Python中的列表。 1.定义列表 列表(list)是一种有序的组合数据类型,可以存放零到多个元素,每一元素可以是数值 型、字符串型、列表以及后面要介绍的字典等任意一种数据类型。 定义列表时,所有元素都写在一对方括号“[]”中,每两个元素之间用逗号分隔。不包含 任何元素的列表称为空列表。 【例3-6】 定义存储一名考生数据的列表,并输出列表中的内容。 1 #定义存储一名考生数据的列表 2 student=['KS00001','张珊',109,120,114,78,82,90] 3 print(student) #输出该列表 运行程序例3-6,结果如图3-7所示。 图3-7 例3-6运行情况 现在,我们已经可以表示一名考生的数据了。 2.二维列表 由于列表包含的元素还可以是列表,我们可以使用列表的这一特性存储表3-1中的所 有考生的数据。此时,列表中的每个元素都是保存某位考生数据的列表,整个列表就存储了 所有考生的数据。这种列表嵌套列表的结构,称为二维(二级)列表。 【例3-7】 定义二维列表存储表3-1中所有考生的数据,要求每个元素是每名考生的 数据。 1 #定义二维列表存储表3-1 中的考生数据,列表元素是每名考生的数据 2 stu1=[ 3 ['KS00001','张珊',109,120,114,78,82,90], #保存第一位考生数据 4 ['KS00002','李思',123,116,137,84,92,94], #保存第二位考生数据 5 ['KS00003','王武',133,129,132,83,85,78] #保存第三位考生数据 6 ] 7 print(stu1) 上面代码中的二维列表stu1采用的是按行存储方式,它的每个元素是一个一维列表, 存储的是一名考生的准考证号、姓名和6门课程的成绩。 程序例3-7的运行结果如图3-8所示。 图3-8 例3-7运行结果 现在,我们已经可以表示多名考生的数据了。 【例3-8】 定义二维列表存储表3-1中的考生数据,要求每个元素是数据的一个 属性。 1 #定义二维列表存储表3-1 中的考生数据,列表元素是属性信息 2 stu2=[ 62 Python程序设计基础———思维、认知与创新 3 ['KS00001','KS00002','KS00003'], #按顺序保存所有准考证号 4 ['张珊','李思','王武'], #按 顺序保存所有考生姓名 5 [109,123,133], #按顺序保存语文成绩 6 [120,116,129], #按顺序保存数学成绩 7 [114,137,132], #按顺序保存英语成绩 8 [78,84,83], #按顺序保存历史成绩 9 [82,92,85], #按顺序保存地理成绩 10 [90,94,78] #按顺序保存政治成绩 11 ] 12 print(stu2) 上面代码中的二维列表stu2采用的是按列存储方式,它的每个元素仍然是列表,但存 储的是考生数据中的属性,包括准考证号、姓名、语文成绩、数学成绩、英语成绩、历史成绩、 地理成绩、政治成绩。 程序例3-8的运行结果如图3-9所示。 图3-9 例3-8运行结果 3.访问列表 Python中列表的访问(又称检索),通过“列表变量名[下标]”的形式访问列表中的某个 元素。下标是指某个元素在列表中的位置,既可以从前往后数每个元素的位置,也可以从后 往前数每个元素的位置。注意,从前往后数时,下标从0 开始数,依次增加1;从后往前数 时,下标从-1开始,依次减少1。 例如,对于student=['KS00001','张珊',109,120,114,78,82,90]这个列表,各个元素的 下标如表3-3所示。 表3-3 列表student各元素的下标 列表元素KS00001 张珊109 120 114 78 82 90 从前往后数,下标取值0 1 2 3 4 5 6 7 从后往前数,下标取值-8 -7 -6 -5 -4 -3 -2 -1 另外,还可以截取列表中的部分元素形成一个新列表。具体用法如下: ls[下标开始位置:下标结束位置] 其中,ls是定义好的列表变量名,ls[下标开始位置:下标结束位置]表示将ls中从下标 开始位置开始,到下标结束位置之前的那一个元素(不包括下标结束位置的元素),取出来形 成一个新的列表。下标开始位置和下标结束位置均可以省略,下标开始位置省略表示从下 标为0的元素开始访问;下标结束位置省略表示访问到最后一个元素(包括最后一个元素); 两者均省略代表截取整个列表。 【例3-9】 对列表中部分元素的访问。 1 student=['KS00001','张珊',109,120,114,78,82,90] 2 print(student[1:4]) #截取下标为1,2,3 的元素形成新列表'张珊',109,120] 3 print(student[-3:-1]) #截取下标为-3,-2 的元素形成新列表[78,82] 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 63 4 print(student[3:6]) #截取下标为3,4,5 的元素形成新列表[120,114,78] 5 print(student[:4]) #截取下标为0,1,2,3 的元素形成新列表['KS00001','张珊', #109,120] 6 print(student[-3:]) #截取下标为-3,-2,-1 的元素形成新列表[78,82,90] 7 print(student[:]) #取所有元素['KS00001','张珊',109,120,114,78,82,90] 8 print(student[3]) #取单个元素,下标为3,返回值为单个元素120 程序例3-9运行结果如图3-10所示。 图3-10 例3-9运行结果 二级列表的访问可以通过多个方括号“[]”叠加的方式依次访问每级列表中的元素。 【例3-10】 访问二级列表中的元素。 1 #按行存储考生数据 2 stu1=[ 3 ['KS00001','张珊',109,120,114,78,82,90], #保存第一位考生数据 4 ['KS00002','李思',123,116,137,84,92,94], #保存第二位考生数据 5 ['KS00003','王武',133,129,132,83,85,78] #保存第三位考生数据 6 ] 7 print(stu1[0]) #访问第一位考生数据 8 print(stu1[2]) #访问第三位考生数据 9 #stu1[0]返回的是存储第一名考生数据的列表,可以继续通过[]访问其中的元素 10 print(stu1[0][2]) #访问第一名考生的语文成绩 程序例3-10运行结果如图3-11所示。 图3-11 例3-10运行结果 4.列表的常用操作 1)拼接列表 通过拼接运算符即加号“+”可以将多个列表连接在一起,生成一个新列表。 【例3-11】 列表的拼接。 1 stu1=[ 2 ['KS00001','张珊',109,120,114,78,82,90], #保存第一位考生数据 3 ['KS00002','李思',123,116,137,84,92,94], #保存第二位考生数据 4 ['KS00003','王武',133,129,132,83,85,78] #保存第三位考生数据 5 ] 6 stu2=[ 7 ['KS00004','李明',142,125,145,89,95,93], 64 Python程序设计基础———思维、认知与创新 8 ['KS00005','徐晓丽',98,102,119,75,69,81] 9 ] 10 stu3=['KS00006','程鑫鑫',113,129,138,76,82,88] 11 m_stu1 = stu1+stu2 12 print(m_stu1) 13 m_stu2 = stu1+stu3 14 print(m_stu2) 上述程序中,第11行代码将列表stu1和stu2拼接成一个新列表m_stu1,第13行代码 将列表stu1和stu3拼接成一个新列表m_stu2。程序例3-11运行结果如图3-12所示。 图3-12 例3-11运行结果 2)计算列表长度 使用len()方法可以获取一个列表中包含的元素数量,即列表的长度。 【例3-12】 计算列表长度。 1 stu1=[ 2 ['KS00001','张珊',109,120,114,78,82,90], #保 存第一位考生数据 3 ['KS00002','李思',123,116,137,84,92,94], #保 存第二位考生数据 4 ['KS00003','王武',133,129,132,83,85,78] #保 存第三位考生数据 5 ] 6 print('stu1 中的考生人数为:',len(stu1)) 程序例3-12运行结果如图3-13所示。 3)获取列表中的最大元素、最小元素 使用max()方法可以获取一个列表中的最大元素的值,使用min()方法可以获取一个 列表中最小元素的值。 【例3-13】 按列存储多名考生的成绩信息,获取语文的最高分和外语最低分。 1 stu2=[ 2 ['KS00001','KS00002','KS00003'], #按顺序保存所有准考证号 3 ['张珊','李思','王武'], #按顺序保存所有考生姓名 4 [109,123,133], #按顺序保存语文成绩 5 [120,116,129], #按顺序保存数学成绩 6 [114,137,132], #按顺序保存英语成绩 7 [78,84,83], #按顺序保存历史成绩 8 [82,92,85], #按顺序保存地理成绩 9 [90,94,78] #按顺序保存政治成绩 10 ] 11 print('三名考生中语文最高成绩为',max(stu2[2]))#语文成绩的最大值 12 print('三名考生中英语最低成绩为',min(stu2[4]))# 英 语成绩的最小值 程序例3-13运行结果如图3-14所示。 图3-13 例3-12运行结果图3-14 例3-13运行结果 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 65 4)向列表中增加元素 (1)使用append()方法可以向列表末尾追加元素。这种方法每次可以向列表的末尾追 加一个元素。 (2)使用insert()方法可以将一个元素插入列表的指定位置。insert()方法有两个参 数,第一个参数用来指定插入的下标位置(下标从0开始计数),第二个参数是要插入的元 素值。 【例3-14】 向列表中增加元素。 1 stu1=[ 2 ['KS00001','张珊',109,120,114,78,82,90], # 保存第一位考生数据 3 ['KS00002','李思',123,116,137,84,92,94], # 保存第二位考生数据 4 ['KS00003','王武',133,129,132,83,85,78] #保存第三位考生数据 5 ] 6 ls1 = ['KS00005','李明',142,125,145,89,95,93] 7 ls2 = ['KS00004','徐晓丽',98,102,119,75,69,81] 8 stu1.append(ls1) 9 print(stu1) 10 stu1.insert(3,ls2) 11 print(stu1) 上述程序中的第8行代码是将列表ls1作为一个元素插入二维列表stu1的最后;第10 行代码是在将ls2插入stu1第4个元素的位置。程序例3-14运行结果如图3-15所示。 图3-15 例3-14运行结果 请思考并试一试:如果insert方法中给出的第一个参数值超出列表的下标范围,会怎 么样呢? 5)查询列表中的元素 使用运算符in或notin查询某元素是否存在列表中,返回结果是逻辑真(True)或逻辑 假(False),分别表示元素在列表中或不在列表中。 【例3-15】 判断列表中是否存在某个数据元素。 1 stu1=[ 2 ['KS00001','张珊',109,120,114,78,82,90], 3 ['KS00002','李思',123,116,137,84,92,94], 4 ['KS00003','王武',133,129,132,83,85,78], 5 ['KS00004','李明',142,125,145,89,95,93], 6 ['KS00005','徐晓丽',98,102,119,75,69,81] 7 ] 8 print('张珊' in stu1[0]) #查找元素张珊是否存在于列表中 图3-16 例3-15运 行结果 上述程序中的第8行代码中,由于张珊在第一个列表元素stu1[0] 中,因此“'张珊'instu1[0]”返回的结果为True。例3-15运行结果如 图3-16所示。 请思考并试一试:如果要判断学生“贾兰”是否在列表stu1中,应该如何处理? 会输出 6 6 Python程序设计基础———思维、认知与创新 什么结果? 列表的常用操作还有很多。例如,使用sort() 方法对列表中的元素排序;使用index() 方法查找某个元素在列表中首次出现的位置;使用count() 方法统计列表中某个元素出现 的次数;使用del() 方法删除列表中某个元素;使用clear() 方法清空列表;等等。此处不再 一一展开,有需求和感兴趣的读者可以自行查阅相关文献。 3.3.2 如何用Python模拟生成考生数据 前面已经明确了要模拟的考生数据,包括准考证号、姓名和6科成绩等信息,也知道了 一名考生的数据可以放在一个一维列表中,所有考生的数据可以放在一个二维列表中。那 么,下面要解决的问题就是如何模拟生成这些考生的数据。 3.1 AI 助学 3.2. 我的问题:模拟生成数据的方法有哪些? 文心一言回答:模拟生成数据的方法有很多种,以下是常见的方法。 (1)随机数生成法:通过随机数生成器生成一系列随机数,可以模拟各种分布的数据。 (2)参数建模法:根据已知的数据分布规律和参数,建立数学模型,通过模型生成符合 要求的数据。 (3)机器学习方法:利用机器学习算法对大量数据进行训练和学习,然后生成新的 数据 ( 。 4)自然语言处理法:通过自然语言处理技术,从已有的文本数据中提取有用的信息, 生成新的数据。 数据 ( 。 5)图像处理法:通过图像处理技术,从已有的图像数据中提取有用的信息,生成新的 (6)传感器数据模拟:利用传感器模拟数据,可以模拟各种传感器数据,如温度、湿度、 压力等。 (7)蒙特卡洛模拟:通过蒙特卡洛方法,模拟各种随机事件和概率分布,生成符合要求 的数据。 这些方法各有优缺点,应根据具体需求选择合适的方法。同时,也需要注意数据的准确 性和可信度,以避免误导和产生不必要的损失。 在AI 的帮助下,我们了解了用计算机模拟生成数据有很多方法。对于初学者,感觉随 机数生成法比较简单,可以先选择学习和使用这个方法。 3.2.随机数生成数据的方法 3.2 Python标准库中的random 模块用来生成随机数,可以生成随机浮点数、整数、字符串, 还可以随机选择列表中的一个元素等。Python标准库中的函数不能直接使用,必须用 import关键字导入后才能使用。 Random 模块包含了大量的方法,用于不同场景的随机数生成,有需求或感兴趣的读者 可以查阅官方文档获取更多用法。下面仅介绍常用的几个方法。 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 67 1.random()方法 random.random()可以随机生成一个实数,取值范围为[0,1)。 2.uniform()方法 random.uniform(x,y)可以随机生成一个实数,取值范围为[x,y]。 3.randint(a,b)方法 random.randint(a,b)可以随机生成指定范围内的一个整数,取值范围为[a,b]。 【例3-16】 random 常用方法示例。 1 import random #加载random 2 print(random.random()) #随机产生一个[0,1)的实数 3 print(random.uniform(2,4)) #随机产生一个[2,4]的实数 4 print(random.randint(0,100)) #随机产生一个[0,100]的整数 例3-16运行结果如图3-17所示。 现在,我们已经可以随机生成一门课程的高考成绩了。 4.choice(seq)方法 random.choice(seq)可以随机选择列表或字符串中的一个元素。 【例3-17】 从一组表示姓的字符串中随机选择一个字符串,再从一组表示名的字符 串中随机选择一个字符串,组成一个人的姓名。 1 import random #加载random 2 #表示姓的列表 3 last_names = ['赵', '钱', '孙', '李', '周', '吴', '郑', '王', '冯', '陈', '褚', '卫', '东方', '沈', '韩', '杨', '欧阳', '秦', '尤', '许', '姚', '邵', '堪', '黄埔', '祁', '毛', '禹', '狄', '米', '贝', '明', '臧', '计', '伏', '成', '戴', '谈', '宋', '茅', '庞','熊', '纪', '舒', '屈', '项', '祝', '董', '梁'] 4 #表示名字的列表 5 first_names = ['明', '红', '强', '芳', '建', '恺', '凯', '超', '梓涵', '玉', '宝强', '钗', '丽', '云', '来', '圆', '媛媛', '一', '天', '东胜', '栋', '致', '茜', '倩', '志摩', '国庆', '年', '泽', '熙', '那', '和', '远', '允', '妙', '家', '伟', '贤', '然', '笑', '冉', '乾', '坤', '琼', '潇', '雯', '瑶', '翊', '墨', '华'] 6 #随机生成一个中文姓名 7 last_name = random.choice(last_names) #在姓氏列表中随机选择一个姓氏 8 first_name = random.choice(first_names) #在姓名列表中随机选择一个姓名 9 print(last_name+first_name) #将姓氏与姓名拼接成一个名字 运行一次程序会生成一个姓名,再运行一次程序将会随机产生另一个姓名。例3-17程 序的一次运行结果如图3-18所示。 图3-17 例3-16运行结果图3-18 例3-17运行结果 现在,我们已经可以随机生成一名考生的姓名了。 3.3.2.3 模拟生成多个数据 我们已经能够生成一个成绩,那么如何生成一名考生的6门科目的成绩呢? 又如何生 68 Python程序设计基础———思维、认知与创新 成多名考生的数据呢? 事实上,这样的处理都是不断重复某一操作的过程。对于一名考生的6门科目的成绩, 先随机生成一门科目的成绩,再随机生成第2门科目的成绩,重复此项操作,直到完成所有 6门科目的成绩的生成。对于生成所有考生的数据也类似,先随机生成一个考生的数据,再 生成下一个考生的数据,直到完成所有考生的数据生成。 这种重复操作的处理过程可以使用Python中的循环语句实现。下面介绍Python循 环语句的使用方法。 1.range函数 range函数用来生成一个数据序列,其语法格式为: range([beg],end,[step]) 其中,beg为起始数值,end表示终止数值(注意生成数据中不包括end),step为步长(允许为 负值)。如果step省略,则默认以1为步长;如果beg省略,则默认从0开始。 【例3-18】 range函数的功能示例。 1 print(range(0,6)) #生成数据序列为:0,1,2,3,4,5 2 print(range(1,101,2)) #生成的数据序列为100 以内的奇数,1,3,5,7,… 2.for语句 for语句是专门用于处理循环的语句,其语法格式为: for 循环变量名in 可迭代对象: 语句序列 其中,可迭代对象可以理解成一个数据序列,如字符串、列表或range方法返回的数字序列。 for循环执行过程:循环变量依次取可迭代对象中的每个值,执行“语句序列”进行相应 的数据处理,当没有迭代对象时循环停止。 【例3-19】 用for循环生成某名考生6门课程的高考成绩(此处假设各门课程成绩的 最高分均为100分)。 1 import random #加载random 2 Score=[] #定义一个空列表,用于存放6 科成绩 3 for i in range(0,6): #循环变量i 从0 开始到5 结束 4 Score.append(random.randint(0,100)) #随机生成1 科成绩放入列表中 5 print(Score) 上述程序中的第3行代码和第4行代码是for循环语句,通过第3行代码中的循环变 量i从0到5的6次取值,重复了6次操作,模拟生成了6科课程。第4行代码是要重复进 行的操作,random.randint(0,100)是随机生成一个分数为0~100的成绩,然后使用列表 图3-19 例3-19运行结果 Score的append()方法,将生成的成绩追加到列表中。 例3-19的运行结果如图3-19所示。 【例3-20】 假设准考证号是以“KS”开头、长度固定为7位 的字符串,取值由“KS00001”依次增加,“KS00002”、“KS00003”、“KS00004”……。使用for 循环生成10个准考证号。 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 69 1 s_no=[] #定义一个空列表 2 for i in range(1,11): #循环变量i 从1 开始到10 结束 3 num ="KS" + str(i).zfill(5) #生成第i 个准考证号 4 s_no.append(num) #将生成的准考证号添加到列表s_no 中 5 print(s_no) 在程序的第3行代码中,首先使用str(i)将循环变量的值转换为String类型;然后调用 字符串的zfill()方法,生成形如“00001”的字符串(当i=1时);最后再使用“+”将“KS”和 “00001”进行拼接,生成准考证号。例3-20的运行结果如图3-20所示。 图3-20 例3-20运行结果 关于循环语句和for循环,可扫描二维码学习更多细节。 3.3.2.4 模拟生成相同的数据 细心的读者应该已经发现了一个问题,每次运行程序随机生成的数据都不一样。如果 想每次运行程序都能随机生成一样的数据,我们可以通过random 的seed()方法,设置一个 随机种子,使得每次运行程序生成的数据都一样。 【例3-21】 随机种子的使用。 1 import random 2 #不加随机种子 3 print("不加随机种子生成的数据:") 4 for i in range(3): 5 score1=[] 6 #随机生成6 个100 以内的整数,并加入score1 列表中 7 for j in range(6): 8 score1.append(random.randint(0,100)) 9 print(score1) 10 #加随机种子 11 print("加随机种子生成的数据:") 12 for i in range(3): 13 score2=[] 14 #随机生成6 个100 以内的整数,并加入score2 列表中 15 random.seed(1) 16 for j in range(6): 17 score2.append(random.randint(0,100)) 18 print(score2) 上面代码中的seed()是随机数生成器random 的一种方法,用于设置生成随机数的种 子。种子是一个整数。通过设置相同的种子,就可以得到相同的随机数序列。 第3~9行代码,没有添加随机种子,循环三次,每次随机生成的数据均不相同。 7 0 Python程序设计基础———思维、认知与创新 第11~18 行代码也是循环三次,但每次生成的数据均相 同,这是由于在第15 行代码中,为每次循环都设置了同一个 种子值1,所以三次循环生成的随机数是相同的。当然也可 以设置不同的种子,生成不同的随机数序列。 例3-21 的运行结果如图3-21 所示。 现在,我们已经可以生成多科成绩数据以及多名考生 的 数据了 。 3.3.3 如何用Python保存考生数据 使用前面的方法,已经能够使用Python模拟生成考生的数据了。但是,我们发现每次 运行程序都可以生成考生数据,但程序运行结束或关闭计算机后,必须重新运行程序才能获 得考生数据。这是由于运行程序生成的数据被存储在计算机的内存中,而内存中的数据不 会被永久保存,程序结束或计算机关机都会丢失。 是不是有什么方法不需要每次都去运行程序获得考生数据,而是将一次生成的考生数 据永久保存起来,用于后面实现高考平行志愿录取任务呢? 事实上,我们可以将生成的考生数据存储在文件里,文件被保存在外存(硬盘、U盘等) 中,这样就可以实现这些数据的长期保存及重复利用。这就要学习将内存中的数据保存到 文件中的方法。下面介绍将数据存储到文件中涉及的几个概念,以及使用Python对CVS 文件进行操作的相关方法。 3.3.关于数据的几个概念 3.1 1. 数据元素 数据元素也称为结点或记录。一个数据元素可由若干数据项(属性)组成。例如,表3-1 所示的考生数据,每名考生的数据就是一个数据元素,包括准考证号、姓名和语文、数学、英 语、历史、地理、政治6科成绩数据。 2. 一维数据 一维数据是指数据元素由一个因素即可确定。例如,一名考生的数据就是一个一维数 据,如表3-4所示。表中的阴影部分是一维数据,可以看出,一个数据项只由该数据项所在 位置这一个因素就可以确定。例如,第1位的数据是准考证号,第2位的数据是姓名,第8 位的数据是政治成绩。我们知道,一维数据可以使用Python中的列表来表示。 表3- 4 一维数据示例 图3-21例3-21运行结果 含义准考证号姓名语文数学英语历史地理政治 位置1 2 3 4 5 6 7 8 数据KS00001 张珊109 120 114 78 82 90 3. 二维数据 二维数据由多个一维数据组成,二维数据中的某项数据需要由两个因素共同决定。如 第3章获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件71 表3-5所示,多名考生的数据就是二维数据。表3-5中的阴影部分是二维数据,可以看出, 一项数据需要由该数据项所在的行号和所在的列号两个因素才能确定。例如,116 这个成 绩,需要由该数据所在的行号2和所在的列号4这两个因素才能确定。我们也已经知道,二 维数据可以使用Python中的二维列表来表示。 表3- 5 二维数据示例 含义准考证号姓名语文数学英语历史地理政治 列号 行号1 2 3 4 5 6 7 8 1 KS00001 张珊109 120 114 78 82 90 2 KS00002 李思123 116 137 84 92 94 3 KS00003 王武133 129 132 83 85 78 … … … … … … … … … 4. 计算机文件 计算机文件(以下简称文件), 是一种存储在计算机硬盘、软盘、光盘等存储介质上的数 据的集合,内容可以是文本、图像、音频、视频、程序等。一个文件的名字通常由一个文件名 和一个文件扩展名构成。文件扩展名来标识它所属的类型,便于识别和管理。 5.CSV 文件 CSV(Comma-SeparatedValues)是一种国际通用的数据存储格式文件,文件扩展名为 csv,可以使用记事本、Excel等软件打开CSV 文件。CSV 文件中每行对应一个一维数据, 数(.) 据各数据项之间默认用英文逗号分隔。如果有缺失数据,也要保留逗号,使得各项数据都 有它的位置。CSV 文件中的多行一维数据就够构成了一个二维数据。CSV 文件的第一行 可以是列标题,也可以直接存储数据(即没有列标题)。 图3-22 示意了用Excel打开的带列标题的CSV 文件和不带列标题的CSV 文件。 图3-22 带列标题CSV 文件和不带列标题CSV 文件 6. 类与对象 类是对同一类对象的一个抽象,而对象则是类中一个具体的实体。例如,圆是一个类, 而半径5cm,圆心(0,0)的圆就是一个具体的对象。OOP(ObjectOrientedProgramming) 就是通过抽象对象特征来编写程序的一种方法,称为面向对象程序设计方法。Python中的 库都采用了OOP 。 类通常规定了一个对象可以包括哪些数据,以及对这些数据进行哪些处理。类中的数 72 Python程序设计基础———思维、认知与创新 据用来表示对象的静态特征———属性,类中进行的处理用来表示对象的动态特征———行为。 类中要进行的处理在很多场合被称为方法。一个类可以有(创建)多个对象。例如,计算圆 的面积和周长的问题,可以抽象出一个关于圆的类,类中的数据部分包括圆心的位置和半 径;类中的处理部分包括输入圆心、输入半径、计算面积、计算周长和输出结果等。 事实上,我们已经接触过很多次类、对象和方法。例如,例3-21中的score1是一个列表 类的对象,append()是列表类的一个方法,score1.append(random.randint(0,100))是对象 score1执行具体方法append(),将随机生成的数据追加到对象score1自己的数据中。 关于类与对象,可扫描二维码学习更多细节。 3.3.3.2 使用Pandas进行CSV 文件的读写操作 Pandas是Python中专门用于数据处理和数据分析的第三方库,需要下载和安装。它 提供了强大的数据处理和分析功能,包括数据读取、清洗、转换、合并、分析、统计和可视化 等。我们使用Pandas读写考生数据的文件。 Pandas提供了Series和DataFrame两种数据结构,分别用于处理一维数据和二维数据。 这两种数据结构能够满足处理金融、统计、社会科学、工程等领域里绝大部分问题的需求。 1.Series简介 Series用于处理一维数据。第4章将进一步介绍。 2.DataFrame简介 DataFrame是具有行标签和列标签的二维表格型数据结构,与Excel表类似。我们要 处理的考生数据是二维数据,就可以使用Pandas中的DataFrame。 DataFrame是一个抽象的类,要使用DataFrame中的具体方法,如读写文件,必须有一个 具体的DataFrame类对象。创建一个具体的DataFrame对象,需要使用pandas.DataFrame()方 法,其语法如下: pandas.DataFrame(data, index, columns, …) 其中,pandas.DataFrame()方法主要参数的含义如下: ● Data是所创建的DataFrame对象中的数据来源,其类型可以是列表、字典、Series或 DataFrame对象等。 ●index是DataFrame对象数据的行标签,如果未指定则默认为RangeIndex,即(0,1, 2,…,n-1),n为行数。 ● columns是列标签,如果未指定也默认为RangeIndex,即(0,1,2,…,m-1),m为列数。 第3章 获取高考原始成绩数据———Python的字符串、列表、for循环、pandas和文件 73 有需要或感兴趣的读者可以查阅Pandas官方文档,查看pandas.DataFrame更多的参数。 【例3-22】 创建并输出DataFrame对象。 1 ''' 2 1.使用pandas 前需先使用import 将pandas 加载到程序中 3 2.可以用as 关键字给pandas 起个别名,程序中用到pandas 的地方都可以换成别名 4 ''' 5 import pandas as pd #pd 是pandas 的别名 6 stu1=[ 7 ['KS00001','张珊',109,120,114,78,82,90], #保存第一位考生数据 8 ['KS00002','李思',123,116,137,84,92,94], #保存第二位考生数据 9 ['KS00003','王武',133,129,132,83,85,78] #保存第三位考生数据 10 ] 11 #创建DataFrame 对象df,df 对象的二维数据来自stu1, 并设置列标题 12 df = pd.DataFrame(stu1,columns=['准考证号','姓名','语文', '数学', '英语', '历 史', '地理', '政治']) 13 #输出DataFrame 对象df 14 print(df) 例3-22运行结果如图3-23所示。 图3-23 例3-22运行结果 在图3-23中,最左侧的列的“0,1,2”是默认的行标题;最上面的“准考证号姓名语文 数学英语历史地理政治”则是在第12行代码中创建df对象时设置的列标题。 3.CSV 文件的读写操作方法 Pandas中DataFrame的to_csv()方法是将DataFrame对象的数据写入CSV 文件; Pandas的read_csv()方法用于读取CSV 文件中的数据,并返回一个DataFrame的对象。 1)写文件 DataFrame的to_csv()方法的功能是写文件。 该方法有很多参数可以设置,除了必须给出写入文件的路径和名称外,其他参数都可以 缺省,即使用默认值。一些常用的参数含义如下: ● header(boolorlistofstr,default=True):是否写入列名作为文件的第一行。如果 给定为字符串列表,则假定它是列名的别名。 ●index(bool,default=True):是否将行索引写入文件。 ● mode(str):对于路径或类文件对象,写入的模式('w' 或a' ')。默认为'w',表示重写, a' '表示追加方式写入。 ● encoding(str,optional):使用的字符集编码类型。 其他参数不再一一展开,有兴趣和有需求的读者可以自行查阅。 【例3-23】 使用Pandas将表3-1中的三位考生数据写入D盘的myproject目录下名 为“写入的考生数据.csv”文件中。 使用Pandas的to_csv()方法非常简单,只需在例3-22的代码最后添加如下的第10行 代码即可。