因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:用户
您可以查看与复制此页面的源代码。== Python程序设计课程主页(2020年秋季学期) ==
Teacher: [http://hlt.suda.edu.cn/~zhli 李正华]
Teaching Assistant: 周厚全、刘泽洋、周仕林
上课时间和地点、QQ群
周一13:30-15:20卫校301;
周五13:30-15:20理工楼153
周二13:30-15:20理工楼238、247(上机);
python-2020学习交流QQ群:893402501
教材的名字:零基础学习并理解Python
特点:1)把重点放到理解上,建立基本概念;2)重视英语学习,尽可能多的给出英语术语翻译;3)多画流程图、多给出图例,考虑latex画图。
== 考试安排 ==
* 第一次考试:11.11(周三),考试内容:基础、分支、列表、循环 ([http://hlt.suda.edu.cn/LA/teach/python-2020-fall/考试成绩-anonymous.xlsx 考试成绩])
* 第二次考试:12月9日(周三)晚上:元组 字符串 字典 集合
* 第三次考试(期末):1月
* 考试形式:上机考试
** 选择题
** 编程题:每一道题对应一个函数(给定了函数名,不能随便修改),所有函数放到一个.py文件中
*** 得至少练一次?可否开一下系统?
* [http://192.168.125.3/python/ 考试信息网站]
=== 2020.11.3 模拟考试 ===
* 考试时间:2020.11.3 13:45-15:00
* 考试题型:5道选择题(不会没关系,快速做完)、3道编程题
* 考试内容:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/2020-11-03-SimExam.zip 2020-11-03-模拟考试试题](zip包的解压缩密码是:Py202011031230)
* 模拟考试总结
常见问题:
a. 语法错误:程序中出现语法问题将会导致判为0分:
1. if中出现逗号,例如:
if a0, a1, a2, a3, a4, a5==0:
2. else后面带表达式:此处应该用elif
3. 程序不完整(unexpected EOF):例如用if...else...时,else直接一个冒号就结束了,如果想空掉某些位置请使用pass
4. if后没有冒号
5. 小于等于运算符写错:应该是<=而不是=<
6. 重复def
7. 使用了中文的括号
8. 缩进问题
9. 使用未赋值的变量,尤其是在if判断的时候会出现这样的问题,例如:
if x>0:
a = 1
print(a)
b. 变量使用问题:在使用一个变量时,应该首先确保这个变量已经被赋值,同上。
c. 在代码中使用input导致超时:我们调用你的程序会遇到input()导致无限等待。
d. 误用中括号,例如:
return x, [.....]/5
e. 其他审题要清楚,注意特殊情况下的结果是否与题目给出的样例一致。
注意:考试时,提交的.py中不能有input() print()。
=== 2020.11.10模拟考试 ===
* 考试时间:2020.11.10 13:40-15:00
* 考试题型:1道选择题、3道编程题
* 考试内容:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/2020-11-10-SimExam.zip 2020-11-10-模拟考试试题]
== Mooc混合式教学==
中国大学慕课 Python程序设计 苏州大学 朱晓旭等
请同学们同步学习这个网课。
理论课上,我会留一些时间,来针对网课的内容进行讲解、答疑。
== 参考资料 ==
* 何俊老师的Python课程教学网站
** [http://web.suda.edu.cn/hejun/ 校外链接]
** [http://192.168.125.7/local_python/index.html 校内链接]
* runoob
** [https://www.runoob.com/python3/python3-tutorial.html python3]
** [https://www.runoob.com/python2/python2-tutorial.html python2]
== 实验课安排(有问题多主动问,Python不是教会的,而是不断动手、思考学会的) ==
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/实验报告系统使用手册(学生).docx 实验报告系统使用手册(学生).docx]
=== 实验报告说明 ===
实验报告由两部分组成:
* 实验报告:学号-exp-x.pdf (x表示第几次实验)
** 注意文件命名格式,必须用pdf文件
** 包含题目、流程图、解题思路、运行结果截图、遇到什么问题及如何解决的、总结有哪些收获、对老师的建议
** 每次会提供一个基本的实验模板,学生按照自己的方式去安排报告的内容
** 选择三道较难的题目,先画流程图,然后写代码。可以手画流程图然后拍照,也可以用画图软件去画。其他题目不用画流程图。
* 代码:学号-exp-x.py
** 把所有题目的代码放到一个py文件中,不要压缩,在提交的时候点击附件,上传相应实验的.py文件。
** 注意可读性,方便老师批改,可以写一些必须的注释
注意事项:
* 抄袭会严惩!当次实验成绩清0!
* 实验报告、代码,要保留好,不要删除,期末的时候可能要统一放到一个文件夹中,交给老师。
* 除了基本的题目,还可以额外做老师在课堂上提出的思考题、扩展题。
* 根据认真程度、完成的质量、可读性等,来综合评分
* 每次作业批改后,会在理论课或上机课上进行讲解,重点是讲大家常见的错误。
* 如果系统中没有给出分数,则可以撤销提交并重新提交。
往年的习题集:
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python习题.pdf 习题集PDF] ([http://hlt.suda.edu.cn/LA/teach/python-2020-fall/python-ch10.rar 习题相关数据文件])
=== 扩展题目(选做,可以放到实验报告中) ===
顺序结构题目:
1)输入三个变量的值,然后按小到大顺序输出。
2)BMI指数(身体质量指数,Body Mass Index)是目前国际上常用的衡量人体胖瘦程度及是否健康的一个标准。
体质指数(BMI)=体重(kg)÷身高^2(m)
3)编写程序实现华氏温度到摄氏转换
转换公式:
摄氏度C=(华氏度-32)乘以(5/9)
华氏度F=32+(9/5) 乘以 摄氏度C
4)从键盘输入一个三位整数n,输出其逆序数m。例如,输入n=127,则m=721。
-----
分支结构题目:
(1)判断年份year是否为闰年。
(2)判断ch是否为小写字母。
(3)判断m能否被n整除。
(4)判断ch既不是字母也不是数字字符。
(5)输入年月,求该月的天数。
(6)输入一个时间(小时:分钟:秒),输出该时间经过5分30秒后的时间
(7)根据bmi情况,输出不同的信息:
if bmi<18.5:
print("过轻")
elif bmi<25:
print("正常")
elif bmi<28:
print("过重")
elif bmi<32:
print("肥胖")
else:
print("非常肥胖")
-----
循环结构题目:
从m到n数字求和
判断一个数字是否为素数(质数)
判断一个字符串是否为回文('abccba', 'aba')
求一个浮点数(>0)的根号,可以有多种方法。例如:平方根迭代公式x1=1/2*(x0+a/x0)
求两个整数a与b的最大公约数、最小公倍数
输出[100,1000)以内的全部完数(因子之的和等于自己,如6=1+2+3)
用字符'*'输出不同的形状,如等边三角形,等腰三角形,直角三角形
打印9*9乘法表
角谷猜想:
是指对于任意一个正整数
如果是奇数,则乘3加1
如果是偶数,则除以2
得到的结果再按照上述规则重复处理
最终总能够得到1
欧几里得算法(辗转相除法)求最大公约数
num1,num2=eval(input("请输入两个正整数"))
if num1
num1,num2=num2,num1 #保证num1大
while num1%num2!=0:
temp=num1%num2
num1=num2
num2=temp
print("最大公约数是:",num2)
哥德巴赫猜想
哥德巴赫->欧拉
任一大于2的偶数都可表示为两个素数之和
1+1
陈景润
任何一个充分大的偶数都可以表示成一个素数和一个不超过两个素数的乘积之和
1+2
猜数字
计算机产生一个1-10000之间的随机数
人去猜
计算机提示
偏大
偏小
猜对
显示猜的人所猜的次数
-----
列表扩展题目:
例:给定一个数字列表,将每个元素求修改为其绝对值,然后返回该列表
l9 = [1,-3.39,7,-999]
例:从键盘输入数字到列表(输入非数字则停止),并对列表进行排序(从小到大),然后返回列表
例:给定一个列表,返回某元素在列表中的所有下标,作为一个列表返回
l1 = [1,'a',2,3]
value = 1
例:实现reverse功能
例:二分查找(一定要亲手实现一下)
例:排序算法
例:矩阵乘法实现:随机产生矩阵中的数字,用嵌套列表来存储
* 2020.10.26:输出当前时间,新输出的时间刷新旧时间。(提示,利用退格符,PyCharm可以,用cmd也可以,IDLE不行)
* 2020.10.23:求平方根,是否还有其他更快的解法(之前讲的是二分查找)
* 2020.10.15:把求平方根的代码,扩展为x为任何大于0的浮点数。注意一定要先画流程图。
=== 思考题目 ===
* 有100只一模一样的苹果,编号1-100。其中99个是正常的,一个被注射了毒药。只要老鼠咬一口毒苹果,一天后则死亡。现在,你有7只老鼠和一天的时间,如何检验出哪个号码的苹果被注射了毒药?
* 蒙特卡洛法求圆周率 pi。正方形面积、圆的面积。当然,圆的面积公式又是怎么来的呢?
=== 实验课常见问题 ===
2020.10.20:
* input()函数从用户得到的输入类型是字符串,不能直接进行数值的运算,需要类型转换。
* 希望一次性input多个数字,可以用字符串split方法:
** lst = list(map(int, input('please input:').split())) #一次性输入多个数字,按空格隔开;并存储到一个列表中
** x, y, z = eval(input('please input two int, using comma as the delimiter: ')) # 输入 3, 5, -4
** lst = eval(input('please input a python list: ')) # 输入 [3, 5, -4],中括号必须有,作为列表对象存储
** a_tuple = eval(input('please input several int, using comma as the delimiter: ')) # 输入 3, 5, -4,作为元组对象存储
* 注意变量 x 与字符串 "x" 之间的区别。
=== 第一次实验报告 2020.10.20 ===
* 截止时间:11月4日20:00前
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/zhenghua-实验1%20python语言基础.doc 报告模板](含基本题目),见csteaching
=== 第二次实验报告 2020.11.3===
* 截止时间:11月15日20:00前
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/zhenghua-实验2%20顺序结构程序设计.doc 报告模板]
=== 第三次实验报告 2020.11.10===
* 截止时间:11月28日20:00前
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/zhenghua-实验3%20选择结构程序设计.doc 报告模板]
* 学生建议:
建议拓展题目不要有包含关系或同类题目,最好少而难。
希望老师能在实验报告后对较难的题目给出较为简便高效的代码,以便于学习。
希望老师上课多讲点知识,有条理一些。
每节理论课可以在群里提前说一下下节课内容,有所准备的话,在课上可以更好的理解。
希望老师能够对稍微大型些的程序做些分析和讲解。
=== 第四次实验报告 2020.11.17===
* 截止时间:12月01日20:00前
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/zhenghua-实验4%20列表.doc 报告模板]
=== 第五次实验报告 2020.11.24 ===
* 截止时间:12月08日20:00前
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/zhenghua-实验5%20循环结构程序设计.doc 报告模板]
=== 第六次实验报告 2020.12.01 字符串与正则表达式 ===
* 截止时间:12月31日20:00前
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/zhenghua-实验6%20字符串与正则表达式.doc 报告模板]
=== 第七次实验报告 2020.12.08 元组、字典、集合===
* 截止时间:12月31日20:00前
* [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/zhenghua-实验7%20元组、字典与集合.doc 报告模板]
== 讲给同学们的话 ==
大学生活、学习的一些建议
* 计算机英语很重要(1000左右单词),有助于理解和记忆;
* 逻辑思维能力很重要,从流程图(或伪代码)锻炼起;
* 多动手、多练习、多思考、多尝试,才能学好编程;
* 编程只是计算机科学与技术这门学科的最基本能力。要想成为顶尖的编程高手,必须对计算机的硬件、操作系统、数据结构、算法等基础理论理解透彻,所以要长期坚持,不断提高自己的计算机素养和基础。
2020.10.23 今天又少了一次课(第5周周五少了一次)。希望大家利用各种资源,抓紧学习。我的课主要以理解为主,把知识串起来。要学好python,要不断写代码、调试。要靠自己
== 讲义记录 ==
=== TODO ===
选择 -> 列表 -> 循环 -> 元组 -> 字符串切片、方法等(讲课顺序)
函数:
递归函数
函数作为参数 sort(key = )
lambda
函数参数:位置型、关键字类型
默认参数
标量Scalar(integer, floating-point number, boolean)
矢量Non-Scalar(字符串string等)
python的特点
high-level(python > c++ > c > 汇编)
C语言能做的,Python都能做?感觉不一定
解释性(interpretative)
面向对象(object)
跨平台、移植性高
2.0和3.0不兼容,语法有一些小的变化
=== 学习朱晓旭老师的PPT ===
in和not in 测试(成员测试,列表、字符串等)
isinstance(3, int)
用单引号或双引号括起来的字符串不可跨行
用三引号括起来的字符串可以是多行的
格式字符串:% format() str.format()
原始字符串:如果不希望字符串转义,前面加r
r”\n”
如果转义后没有意义,那么就是两个字符,如'\A'
转义字符:以反斜杠“\”开头,后跟一个或多个字符(反斜杠称为转义字符,表示的字符称为特殊字符?怎么说比较清晰呢,得看看英文文献,确认一下?)
转义字符具有特定的含义
不同于字符原有的意义,故称转义字符,
主要用来表示那些用一般字符不便于表示的控制代码
eval()函数
其调用格式为:
eval(字符串)
作用是把字符串的内容作为对应的Python语句(表达式?)来执行
逗号:分隔符(元组)
表达式:
单个任何类型的对象或常数
使用运算符连接的变量和常量
函数调用的任意组合
什么是表达式?eval('x=3') vs. x=eval('3')
dir(__builtins__)
可以使用sys.modules.items()显示所有预加载模块的相关信息。
=== Python代码规范(摘自朱晓旭老师PPT)===
缩进:
类定义、函数定义、选择结构、循环结构,行尾的冒号表示缩进的开始
python程序是依靠代码块的缩进来体现代码之间的逻辑关系的,缩进结束就表示一个代码块结束了。
同一个级别的代码块的缩进量必须相同。
一般而言,以4个空格为基本缩进单位,可以通过下面的方法进行代码块的缩进和反缩进:
注释:
一个好的、可读性强的程序一般包含30%以上的注释。常用的注释方式主要有两种:
以#开始,表示本行#之后的内容为注释
包含在一对三引号'''...'''或"""..."""之间且不属于任何语句的内容将被解释器认为是注释
每个import只导入一个模块
如果一行语句太长,可以在行尾加上\来换行分成多行,但是更建议使用括号来包含多行内容。
必要的空格与空行:
运算符两侧、函数参数之间、逗号两侧建议使用空格分开。
不同功能的代码块之间、不同的函数定义之间建议增加一个空行以增加可读性。
适当使用异常处理结构进行容错,后面将详细讲解。
软件应具有较强的可测试性,测试与开发齐头并进。
=== 函数 ===
=== 模块 ===
模块基础:package(包)等以后再学习
random模块的学习和使用
什么是模块?py文件,文件夹组织时,如何import?【后期还会专门学习一下】
help(dir)
dir(math)
help(random)
dir(random)
help(time)
dir(time)
help(time.ctime)
Python默认安装仅包含部分基本或核心模块,但用户可以安装大量的扩展模块,pip是管理模块的重要工具。
在Python启动时,仅加载了很少的一部分模块,在需要时由程序员显式地加载(可能需要先安装)其他模块。
减小运行的压力,仅加载真正需要的模块和功能,且具有很强的可扩展性。
可以使用sys.modules.items()显示所有预加载模块的相关信息。
import 模块名
>>>import math
>>>math.sin(0.5) #求0.5的正弦
>>>import random
>>>x=random.random( ) #获得[0,1) 内的随机小数
>>>y=random.random( )
>>>n=random.randint(1,100) #获得[1,100]上的随机整数
可以使用dir函数查看任意模块中所有的对象列表,如果调用不带参数的dir()函数,则返回当前脚本的所有名字列表。
可以使用help函数查看任意模块或函数的使用帮助。
from 模块名 import 对象名[ as 别名] #可以减少查询次数,提高执行速度
from math import * #谨慎使用
>>> from math import sin
>>> sin(3)
0.1411200080598672
>>> from math import sin as f #别名
>>> f(3)
0.141120008059867
如何自己写一个模块。模块和引用py文件的路径问题?
time模块
=== 字符串和集合 ===
-----
字符串格式化(formating operator)
每个对象都应该有字符串表示,否则就没法输出。
f = 2/3
f.__str__()
print(f)
f.__repr__()
'%10.2f' % f
https://www.cnblogs.com/songdanlee/p/11105807.html
1. %
2. str.format
3. f''
4. format() 不常用
以某种格式将n个相同类型或不同类型的对象转化为一个字符串
'%20s' % [1,2,3]
讲一下基本的即可。
'%d' % 3 # '3'
'%d %d --- %d' % (3, 4, -7) # '3 4 --- -7'
'%d %d --- %d' % (0xff, 0o33, 0b011110) # '377 27 --- 30'
'%8d %5d --- %10d' % (0xff, 0o33, 0b011110) # 默认右对齐
'%-8d %-5d --- %-10d' % (0xff, 0O33, 0b011110) # 左对齐
‘%f’ % 9.9 # 输出浮点数‘9.900000’
‘%10f\n%10f\n%10f’ % (9.9, 12.754, 3.34)
‘%6.3f\n%6.3f\n%6.3f’ % (9.9, 12.754, 3.34) # 占6个字节,小数点后保留3位
‘%10s’ % 'hi'
浮点数指数形式:即用科学计数法表示的浮点数,例如: 45e-5、9.34e2,格式化怎么做?
str.format的优势:可以不考虑类型,可以重用一个参数,可以用dict等复杂类型等(方便)
花括号形式的,runoob
https://www.runoob.com/python/att-string-format.html
f'{}' ...
-----
字典
why:统计词频(英文著作)【效率问题】
定义字典:
{}
工厂函数:zip
字典:可变、key唯一(班级Python成绩)、无序、可迭代
字典的遍历:
for i in d1:
for (i,j) in d1:
for i in d1.keys():
不是序列的可迭代对象:
range
reversed
dict
set
file
内置函数
字典的增删改
字典的方法
嵌套:
姓名 -> 各科成绩;
拷贝:
# 字典是无序的
d1 = {1:'Jan',2:'Feb','Mar':3,'Tuesday':2}
for i in d1:
print(i,':',d1[i])
d1[1] = 'Monday'
d2 = dict([[1,'a'],[2,'b'],[3,'c']])
l1=[1,2,3]
l2=[4,5,6]
d3=dict(zip(l1,l2))
d6={0:[1,2,3],1:[4,5,6]}
d7={}
d7[0] = d6[0]
d7[1] = d6[1] # 浅拷贝
二、字典的特点:
无序;
成对key-value,且key不可以重复;
可变(增加或者删除key) d1={0:'a','a':'b','a':'3'}
三、字典里面的增加,删除
d1.pop('a')
d1
d1['a']=3
d1
d1['b']=[1,2,3]
d1
id(d1),id(d1['b'])#怎么在list中增加一个4
d1['b'].append(4)
d1
id(d1),id(d1['b'])#看到地址都没有发生改变
四、用字典设计比较复杂的数据结构
#方法一,比较死板,可读性比较差
d2={}
d2['001']=['name','M',99,97,30]
d2['002']=['name2','f',99,99,80]
d2['001'][2]
#方法二,可读性更好,字典嵌套字典
d3={}
d3['001']={'name':'zhenghua','gender':'M','grade':{'python':99,'C':90}}
d3['001']['grade']['python']
五、字典的遍历(字典是可迭代的)
for i in d3:
if d3[k]['name']=='zhenghua':
print(d3[k]['grade']['python'])
-----
讲完字典的
字符和数字的转化(不同进制)【不同进制的格式化输出】
http://www.asciitable.com/ ascii码表
汉字的表示(UTF-8/16/32编码的细节不讲),python对字符串默认是采用UTF-8编码。python文件必须是utf-8编码,才可以正常运行?
UTF-16编码到底是什么样子的?
二进制、八进制、十六进制、十进制,放到一起讲
1. 字符ascii码转化
ord('a') # 字符对应的ASCII码(American standard code for information interchange)
chr(97) # 返回与ASCII码对应的字符
2. 字符串中字符表示
print('\x21') 十六进制
print('\41') == print('\041') 八进制
十进制怎么写呢?
3. 字符串格式化中的 %x %o等
'%o %x --- %d' % (0xff, 0O33, 0b011110) # '377 1b --- 30'
'0x%x' % 255 # '0xff'
4. print(0x21) == print(0o41) == print(33) 整数
整数进制转换
hex(1) # 十六进制
bin(255) # 二进制
补码存储(高级部分,要不要将呢)
位运算(二进制、十六进制等时再具体讲)
-----
raw字符串,讲了吧
=== (临时)python字符集 ===
[[Python-2020-fall-python_character_set]]
=== 2020.12.4 字符串格式化,字典 ===
* 板书:[[:文件:2020-12-4-1.jpg]] , [[:文件:2020-12-4-2.jpg]] , [[:文件:2020-12-4-3.jpg]] , [[:文件:2020-12-4-4.jpg]] , [[:文件:2020-12-4-5.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-15-2020.12.4.mp4 第15次理论课]
默认的格式化:每个对象都应该有字符串表示,否则就没法输出。
obj.__str__(),可以转化为字符串,可以print
obj.__repr__(),给python解释器看的
定制地转化为字符串,即格式化 (formatting):
% 操作符(二元):
形式:'formatting-str' % (a, b, c) (注意后面元组的元素数量要和前方数量对的上)
例:
'%d' % 3.1,'%d' 在字符串中代表一个整数,字符串右方的'%'是一个操作符,'%'右方的数是要传入字符串内代替格式化的%d,对于%d可以传入bool、int、float类型对象,此格式化字符串输出 '3'。
'%10d' % 3,输出 ' 3',即为这个整数设置尺寸为10,不够默认用空格填充。
'%010d' % 3,输出 '0000000003',也是设置整数尺寸为10,不够指定0来填充。
'%10d %5s %7.2f',输出' 7 abc 3.74','%5s'是指定宽度为5的字符串,'%7.2f'是指定总宽度为7的浮点数,精度为2。不够的都默认用空格填充。
类型(typecode):
形式:%[(name)][flags][width][.precision]typecode,
中括号[]表示参数是可选的(optional)
name为字典参数,具体怎么用,可以自己研究下
flags对齐和填充标志
width字符串整体宽度,如果设置过小则无效
precision浮点数精度(小数点后的位数)
注:对于有小数部分的数会存在保留进位问题,和计算机存储浮点数的原理有关。
typecode类型编码,即d、f、s等
%d 整数(十进制);%f 浮点数;%s 字符串;
%c 字符(char),对应参数必须为长度为1的字符串,一个ascii码转化为相应字符'A'是65,'a'是97。
ord(),返回一个字符的ascii码(十进制数字),chr()可以把一个ascii码转化成相应字符。
%e =E,转化为科学计数法数字。
%e和%f如果不指定精度,默认会保留到小数点后6位。
%g =G,根据值的大小,选择正常输出,或科学计数法。【没搞明白,我从没用过】
%o、%x分别表示八进制和十六进制,等后面会系统讲解,oct hex bin
思考一个编程题目:输出n以内的乘法表,并且用今天的知识对齐,格式化输出。
字符串format()方法:用{}和:来代替%。可以接受很多参数,顺序也可以指定。
例如:'{:.2f} {:3d} {:5s}'.format(34.2313, 1, 'sca'),返回'34.23 1 sca '
还可以在{}内:的前面指定位置,选择format里面的哪个参数。
例如:'{1:.2f} {0:3d}'.format(1, 34.2313),返回'34.23 1'
还可以使用关键字参数;字典参数;列表参数。
-----
字典
先思考一件事情,如何去把一本书里,全部的字都统计出它们的出现次数。(统计词频)
考虑列表存储[['li', 1], ['zhenghua', 1], ...]
如果列表不排序:从左向右按顺序查询是否存在,如果存在则更新(频率+1),否则在最后位置appen。查询的时间复杂度都是O(n),插入的时间复杂度是O(1)。
如果列表排序,那么可以用二分查找,查询是否存在的时间复杂度为O(logn),但是插入时,要保证排序,因此需要把插入位置后面的元素统一后移,因此插入的时间复杂度为O(n)。
字典为此而生,查询和插入的复杂度都为O(logn)【如果想琢磨怎么做到的,可以给一个提示:内部用平衡二叉树来实现】。
字典(dictionary, dict):容器,可迭代,但是不是序列。每一个元素有key和value一个键值对,key需要是完全不可变对象且不能重复,value可以是任意对象。
在字典中,我们可以通过key,来得到value。
定义方法:
d1 = {a:b, c:d},直接定义。
d1 = dict([(1, 2), ('abc', 3)]),用工厂函数,传入一个可迭代对象,每次返还两项,这个例子会返还{1:2, 'abc':3}
zip函数在这个地方很常用
字典的特点:
可变;
key唯一;
无序,即不能假设key的顺序(用平衡二叉树存储的);
可迭代,但不是序列。
=== 2020.11.30 字符串,字符串的方法,字符串的格式化 ===
* 板书:[[:文件:2020-11-30-1.jpg]] , [[:文件:2020-11-30-2.jpg]] , [[:文件:2020-11-30-3.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-14-2020.11.30.mp4 第14次理论课]
字符串的拼接:s1 += s2,和s1 = s1 + s2是一样的,创建新的对象。
字符串的乘法:s1 *= 3,和s1 = s1 * 3一样,也会创建新的对象。
python的优化:对于完全不可变对象,无论是浅拷贝,还是深拷贝,都只是做名字绑定,不会新创建对象。
s2 = str(s1),虽然str()是一个工厂函数,但是s2仍然和s1是同一个对象,对于"完全"不可变对象s1没有被复制。再例如:
t1 = ((1, 2), 3, 'abc')
t2 = tuple(t1)
此程序,t1和t2的id完全相同,即使是deepcopy也会是完全一样的id。
序列浅拷贝的几种方法:工厂函数;全切片;x1 = x2 * 1;copy.copy
序列深拷贝的方法:copy.deepcopy
如何更深入的学习Python?
学习C/C++,这样才可以了解底层:C++ Primer; STL源码剖析(侯捷);Effective C++;More Effective C++
深入学习和理解python的底层,例如Python源码剖析
in和not in:在一个序列里找到某个元素是否存在。对于字符串,是看一个“子串”,是否存在。而不仅限于一个字符!
例如:'ab' in 'abcd'会返回True。
for i in 'abcd':
...
遍历(迭代iterate)时,会把每一个字符作为单位。为什么是这样呢?为什么不是每两个字符作为一个单元?这是由__iter__()这个特殊方法来决定的。
同学们可以自己写一个类,然后实现__iter__(),来决定如何遍历。如果没有实现__iter__()方法,那么这个类型的对象就不可迭代。
str可以转化为list/tuple对象,例如:list('string')会返回 ['s', 't', 'r', 'i', 'n', 'g']。
list也能转换为str。事实上,所有类型的对象都可以转换为字符串对象。
__str__()和__repr__()这两个特殊方法在起作用
如果你自己写了一个类,没有定义__str__()和__repr__(),那么默认是类型名和内存地址。大家可以做实验试试。
下标索引、切片:
s = 'abcdef' # 下标s[1]='b',s[-1]='e'
s[3:5] # 'de'
s[3:] # 'def'
s[:3] # 'abc'
s[1:5:2] # 'bd',步长为2
s[-5:-2] # 'bcd'
s[::2] # 'ace'
s[::-1] # 'fedcba'
s[-2,-5,-2] # 'ec'
字符串方法:
请大家结合runoob和help英文文档,系统自学一遍。有些方法很少能用上,了解一下即可。用到了再仔细看文档。
s1.capitalize(),把首个字母变成大写。
s1.center()/s1.rjust()/s1.ljust(),用于格式化输出字符串,s1.center()是把字符串居中输出,参数传入可以指定字符串总长度,可以指定用什么字符来补齐空缺,默认为空格。ljust和rjust就是左对齐和右对齐(justify)。
s1.count(),可以看到子串 (sub-string) 出现了几次。
s1.endswith(suffix),字符串以什么结束。
s1.find(),找一个子串第一次出现的位置下标。
s1.index(),和find一样,只不过找不到会报错。
s1.isalnum(),如果字符串至少长度为1,并且全是字母或数字就返回True。
s1.isspace(),判断是否为空白符,有:'\t'制表符;'\n'换行符;'\r'换行符;'\v'垂直制表;'\f'翻页符(flip over);
s1.join(),可以以s1来链接一个可迭代对象,返回一个字符串。
例如:'.'join(['ab', 'cd', 'ef']),会返回'ab.cd.ef'。列表里面的元素需要是str类型。
'.'join('abcd'),返回'a.b.c.d'。
s1.lstrip(),截掉左边的指定字符,默认是空白符,有多少删多少。s1.strip()和s1.rstrip()对应。
s1.maketrans(),字符串映射,可以用于加密。
s1.replace(),把某个子串全部替换为指定字符串。
s1.split(),和s1.join()是相反的,按照分割符(delimiter)切分字符串为列表,例如:'a b c d'.split(),返回['a', 'b', 'c', 'd']。(这个函数会切出来空字符串的)
s1.splitlines(),按'\r'或'\r\n'(作为字符串)或'\n'来切分,分割后,如果最后一个是空字符串,会删掉。其他空字符串不会删掉。
'abc'.center(10) # 占10个字节,居中
'abc'.isalpha() # 字符串中所有字符是否都是字母,返回布尔值
' abc \t\n'.strip() # 去除空白符
'##abc'.strip('#') # 去除指定符号
'abc'.replace('ab','AB') # 替换
'a b c'.split() # 切分字符串
空格符的英文:blank/space characters;
空白符号的英文:whitespace,表示一个集合,\t\n\v\f\r
\r\n都表示换行,为什么需要两个字符?return newline。键盘是由打字机而来的。
学习字符串相关的方法和函数,一定要搞清楚,一个参数是一个字符串,还是一个字符集合?很重要!
出几道题目:
打印各种三角形,直角三角形,等边三角形,如下
*
**
***
*
**
***
*
***
*****
*
* * *
* * * * *
* * * * * * (这个不对,不是等边)
-----
字符串相关的内置函数,建议大家自己系统学习一下所有的内置函数:
https://www.runoob.com/python3/python3-built-in-functions.html
-----
字符串格式化(formatting):将对象以一定的形式转化为字符串。
默认的格式化方法:__str__()和__repr__()
四种方法,后两种不常用
'formatting-str' % (a, b, c)
'formatting-str'.format(a, b, c)
f'formatting-str'
format()
=== 2020.11.27 元组的可变性与不可变性,元组的拷贝,字符串 ===
* 板书:[[:文件:2020-11-27-1.jpg]] , [[:文件:2020-11-27-2.jpg]] , [[:文件:2020-11-27-3.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-13-2020.11.27.mp4 第13次理论课]
元组的可变性和不可变性:不可变,指的是元组中每个元素指向的对象是不可变的;可变,指的是元组中如果含有可变对象,那么元组中的可变对象元素它自身是可以变化的。
例如:t1 = (1, 2, 3),就是一个完全不可以变化的元组;t2 = (1, [3, 4, 5], 2),这个元组中包含一个列表可变对象,那个列表自己是可以更改的,并且元组也会发生相应的“变化”,但是本质上,元组的几个元素事实上仍指向原来的那几个对象。
完全不可变对象:指一个不可变对象,其包含的所有子孙(容器嵌套)也都是不可变对象。如果一个元祖中包含了列表,那么这个元组就不是完全不可变对象。
元组的浅拷贝和深拷贝:既然有嵌套,元组也有浅拷贝和深拷贝。
元组对象绑定:t3 = t2
元组拷贝 (元组切片) :t3 = tuple(t2);t3 = t2[:]; t3 = copy.copy(t2);t3 = t2 * 1(此处t2和上面的例子是一样的)
元组深拷贝:t3 = copy.deepcopy(t2)。递归(recursive)拷贝,直到“完全”不可变对象。
字符串 (string character):最常用的数据类型,是人机交互的基础。
字(character)级别有英文,中文(C),韩文(K),日文(J),中文韩文日文有很多字符,要比英文大的多,所以需要更多字节存储一个字符。汉字一般是2-6个字节存,英文和数字是1个字节存。
有一些字符是控制字符,比如回车符、空格符、响铃符、制表符等。(ASCII码)
字符串的定义:s1 = 'abc',双单引号; s1 = "abc",双双引号;s1 = '''abc'''三单引号;s1 = """abc"""三双引号。
其中,在python中,单引号和双引号没区别,三单引号和三双引号也是没有区别的,三引号可以换行表示同一个字符串,双引号做不到。
单引号和双引号混用:例如, "john' s" 和 'john\' s' 是一样的。如果都使用单引号,因为计算机区分不出来哪个是终止的单引号,所以需要用转义字符 \' 来表示一个单引号,如果是用双引号,计算机就可以很好的区分出来。
三引号用法:定义字符串时多行输入,或者是作为注释 (comment)
注释 (comment) :只要我们按照规范来写好注释,python可以自动生成文档 (document),可以利用help()来查看文档,或者生成网页文档。有两种方法去进行注释。
利用 # 可以直接注释单行。
利用三引号来写注释。
注释规范:对于函数,在def func()的下面一行来写;对于模块,在最顶端来写。
https://www.runoob.com/python3/python3-comment.html
字符串有不可变性 (immutable),并且在内存中连续存储是一个整体,不可拆分。
特殊字符:
续行符 \,在未结束的语句的行末,就是一个续行符,后面不要再跟东西了。这个续航符不仅仅是在字符串里适用,在普通的语句中一样可以续行。例如:
print(a\
, b)
print('ab\
cd')
退格符 \b
响铃符 \a
空字符 \0
换行符 \n
制表符 \t (horizontal)
纵向制表符(vertical):\v
=== 2020.11.23 元组,__str__,__repr__,拆分赋值 ===
* 板书:[[:文件:2020-11-23-1.jpg]] , [[:文件:2020-11-23-2.jpg]] , [[:文件:2020-11-23-3.jpg]] , [[:文件:2020-11-23-4.jpg]] , [[:文件:2020-11-23-5.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-12-2020.11.23.mp4 第12次理论课]
如何去测试一个算法的性能:以顺序和二分查找为例,同一个列表,找很多测试点元素,循环多次测试,分别取其平均值。
iterable和sequence:sequence是一个更严格的概念,zip和enumerate、reversed、文件、range这种类型的对象是可迭代的,但是不是序列。
(区别一个对象是否是可迭代对象可以用for来测试;序列有元组、列表、str)
元组 (tuple):也是一种sequence (内存中连续存储、下标随机访问)。
和列表的主要区别是:immutable 不可变。
元组的定义:t1 = tuple(); t1 = (); t1 = (2, ),必须要有括号内的逗号,否则会优先被python判定为是一个式子,而不是一个只含一个元素的元组。
元组的拼接(concatenation):t1 += (4, 5)和t1 = t1 + (4, 5)是等价的,t1的id已经发生了变化,并不是原来的对象了,新创建了个元组对象。
元组的乘法:t1 = t1 * 3和t1 *= 3,和拼接是一样的,返回新元组对象。
元组的删除:del t1[0]报错,元组不能操作。
元组的切片:返回新元组,切片方式和列表一样。
例:t1[-1:-len(t1)-1:-1],返回一个元组的反转元组。
元组的比较:和列表的比较是一样的,(1, 2, 3, 4, 5) < (1, 2, 3, 4, 5, 1, 2, 3, 4, 5)返回True。
in, not in:查询一个元素在不在元组内,返回bool。
元组和列表的拼接:t1 + l1会报错,列表和元组是不可以拼接的。
元组和列表的相互转换:工厂函数,例:l1 = list(t1),创建一个值和t1元组相等的列表;t1 = tuple(l1),创建一个值和l1列表相等的元组。
元组的方法:只有t1.index()和t1.count(),列表中那些不会对列表操作的方法保留下来了。
序列有关的内嵌函数仍然适用,因为内嵌函数的本质通常是针对一个序列或者一个可迭代对象的,这和是元组或者是列表是没有关系的,然后返回一个新的可迭代对象。例如zip; enumerate; len; max; sum; sorted; reversed; all; any等。
例:len()这个内嵌函数,传入的只需要是一个obj对象即可,只要传入的类有__len__()这个特殊方法,就可以找到它的长度。(什么是类,自己可以提前了解,提前做个实验)
sorted()返回新列表。
类特殊方法的__str__和__repr__:
__str__:当print()时,会输出其返回值。将当前对象转为str对象时,会使用其返回值。
__repr__:一个对象的自我介绍 (给程序员),默认提供对象的类型,内存地址等。可以自己重写,按照自己想要的格式来print。
可以做个实验。
序列拆分赋值:和之前讲的是一样的,例如:a, *b = (1, 2, 3, 4)。
元组的使用场合:
同步赋值,例如,x, y = 5, 7
函数返回多个对象:return a, b, c
字符串格式化‘%d %f’ % (10 ,5)
元组的可变性和不可变性;元组的浅拷贝和深拷贝(下节课)
=== 2020.11.20 查找,二分查找,unpack,列表生成表达式,模块基础 ===
* 板书:[[:文件:2020-11-20-1.jpg]] , [[:文件:2020-11-20-2.jpg]] , [[:文件:2020-11-20-3.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-11-2020.11.20.mp4 第11次理论课]
操作符优先级:一元操作符的优先级普遍高于二元操作符。not的优先级要比and高。
-----
二分查找:
查找:对于列表,有个方法li.index()可以快速地查找到相应value的下标。
顺序查找:如果是查找一个无序的列表,顺序查找的时间复杂度为O(n)
对于一个已经排序好的列表,可以用二分查找,时间复杂度为O(logn)
二分查找 (Binary Search):查找一个已经排序好的列表,例如,对于一个序列[-4, -1, 0, 1, 3, 5, 6, 8, 10]找到元素8的下标,首先确定一个上界和下界,第一轮把上界和下界限定为整个序列,找中位点,第一次会找到3,发现8比3还大,所以把下界重新设置为5,再找中位点,会找到6,发现比8还是小,在把下界设为8,然后再找一次,就会找到8的位置。二分查找中,每一次查找,都会把列表中一半的元素筛除,所以试的次数最大为log2n,其时间复杂度为O(logn)。
编程题目:随机产生一个数字n,然后随机产生n个数字放到列表中,然后.sort(),然后用自己写的二分查找函数来做查询。可以比较一下二分查找和顺序查找的效率。
-----
zip:
苏州大学运动会100米决赛8名队员,按照成绩从小到大排序
nums=[1001,1002,1003,1004,1005,1006,1007,1008]
marks=[10.01,10.89,11.02,11.02,10.02,10.38,10.95,11.45]
这个题目需要把编号和成绩绑在一起作为一个元素,然后排序。C++的做法是用一个结构体,把两种元素绑定在一起。
python的做法:
1)用zip(marks, nums),把两个列表打包,然后指定key为分值来sort()
2)用zip(nums, marks),把两个列表打包,然后指定key为分值来sort(key = lambda x: x[1])
zip后的遍历:
for i, j in zip(nums, marks):
print(i, j)
-----
拆包,解包(unpack):又称为”序列”拆分赋值 (同步赋值),使用赋值语句,将序列拆分,绑定到多个名字上。例如:
x = 5
x, y = y, x
x, y, z = z, x, y
x, y = 5, ‘abc’
赋值语句右侧的对象,被隐式转化为元组(tuple)对象。
e, *f, g = [1, 2, 3, 4],在这个语句中,*f会对应多个元素。最后f的值为[2, 3],是一个列表。
*最多出现一次。左边的变量名数量,可以<=右边序列的len+1。如果左边的变量名的数量为len+1,那么*对应的变量名为空列表
e, *f, g = 'zhenghua',f也是一个列表,每一个元素为长度为1的字符串
-----
列表生成表达式:
[表达式 for 目标1 in 可迭代对象1 [if 条件1] …… for 目标n in 可迭代对象n [if 条件n]]
例:l1 = [i for i in range(1, 100)]
问题1:如何产生10个随机的偶数?
例:l1 = [(x, y) for x in range(5) if x%2==0 for y in range(5) if y%2==1]
最后l1的值为[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
顺序是:给定一个x,遍历所有的y;然给给定下一个x,再遍历所有的y
例:l2 = [abs(i) for i in l1]
例:l3 = [i**2 for i in range(10) if i % 2 == 0]
----
模块(module):
模块化:在程序中,比较重要的思想就是模块化思维,把大问题分解为一个个的小问题。模块化后的一个很大的优势就是小问题的解可以重复使用(重用)。
模块 (module):在python中,一个模块就是一个.py文件。目前常用的模块有:math, random, time。
如何创建并使用自己的模块(DIY)
1)我们以前写过的一个程序prime100.py,其中包含一个is_prime()函数。下面我们演示如何把这个.py作为一个模块使用。
2)在同一个目录下,创建一个新的.py文件,命名为use_DIY_module.py(不在同一个目录下时,如何使用模块,以后会讲)
3)use_DIY_module.py中写
import prime100 (注意不需要.py)
print(prime100.is_prime(7))
4) 运行use_DIY_module.py,就会发现可以了
包 (package):当模块很多时,需要用目录树来组织,整个目录树就叫包。以后会讲。
后面,我们会专门讲解import prime100,具体发生了什么?以及其他使用模块的其他方法。
=== 2020.11.16 列表的方法,关于序列的内嵌函数 ===
* 板书:[[:文件:2020-11-16-1.jpg]] , [[:文件:2020-11-16-2.jpg]] , [[:文件:2020-11-16-3.jpg]] , [[:文件:2020-11-16-4.jpg]] , [[:文件:2020-11-16-5.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-10-2020.11.16.mp4 第10次理论课]
时间复杂度(time complexity)和空间复杂度下去自己了解一下。
列表的方法:
形式:列表名.属性,例如li.append()。其中点符号(.)是属性访问符(attribute access symbol)。
注:属性有数据和方法(method, function)。比如math模块,math.pi就是引用了他的数据,math.sin()就是引用了他的方法。
li.append(self, object, /),self是类的内部属性合集,调用方法的时候就会隐式处理,不用传参。
li.reverse(self, /),就地(In Place)反转,返回值是None。
自己写个myreverse,不允许用切片,也不允许用li.reverse(),两个数交换用x, y = y, x
li.clear(self, /),就地修改,清空列表。
li.remove(self, value, /),就地修改,删除第一个在li中与value相等的元素,否则抛出异常(Exception) ValueError。
如果不想报错,就在删之前确保value在li中存在,可以用in,也可以用try语句。
li.pop(self, index=-1, /),弹出指定下标的元素,默认最后一个,返回被删除的值。
li.copy(self, /),浅拷贝(shallow copy)。
li.count(self, value, /),返回value在li中 出现的次数。
回去写个函数,删除列表中全部的值为value的元素,count和remove配合即可。
li.index(self, value, start=0, stop=9223372036854775807, /),返回第一个值为value的元素的下标。找不到就抛出异常ValueError,一般不会有内存能存下这么大的列表,所以一般不用担心stop。
回去写一个函数get_all_indices(),找到一个列表中全部的值为value的下标,返回列表。li.count()和li.index()配合使用。
li.insert(self, index, object, /),把object插入到index位置,之前的index所指的元素,及其之后的元素,都被往后推一个。插到最后一个位置等于append()。
总结:学一个对象的方法,首先要知道是否会对对象进行修改;其次要知道是否返回一个新创建对象。
上面有三个题目。
li.sort(self, /, *, key=None, reverse=False),就地排序,是稳定的排序,稳定排序指的就是列表中两个相同的值,相对位置不会发生变化。
参数:reverse是排序完之后是否反转,默认是从小到大;key是要传入一个函数,默认为None就是按照简单的比较 (等讲到函数再详细地展开)。
注:"/"和"*"都是用来在函数限定位置的分隔符,"/"前面的都必须用位置传参,如果用关键字指定就会报错,"/"之后就可以用位置指定和关键字指定了,"*"之后必须用关键字指定。如果"/"和"*"要一起用,“/”必须要在“*”前面,顺序不能反,要不然就矛盾了
与序列相关的内置函数:(和列表的方法是不太一样的)
len(); max(); min(); sum(); sorted(); enumerate(); reversed(); all(); any; zip()
sorted(iterable, /, *, key=None, reverse=False),和列表的sort()方法差不多。
enumerate(iterable, start=0),返回一个枚举对象,是一个工厂函数。简单来说,在用for遍历列表的时候,用enumerate()包装一下,就会同时返回循环次数。
reversed(sequence, /),返回一个reversed可迭代对象(iterable),就是把原来的列表做成一个迭代器,在迭代器循环就会得到一个反转的列表。
zip(l1, l2, l3. ...),把几个容器打包,变成一个zip可迭代对象,每次返回的是一个元组,打包了那些容器的相应位置的元素。长度不一取短桶。
视频1:26:10位置,提到了一个加分题目。谁如果做完了,把代码和运行结果截图 发给 刘泽洋助教,前3名同学给加分。不要发到群里。
=== 2020.11.13 列表的拼接,列表的乘法,列表拷贝,列表排序 ===
* 板书:[[:文件:2020-11-13-1.jpg]] , [[:文件:2020-11-13-2.jpg]] , [[:文件:2020-11-13-3.jpg]] , [[:文件:2020-11-13-4.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-9-2020.11.13.mp4 第9次理论课]
第九次理论课:
第一次考试,第一次考试占总成绩比重不是特别大。
一对一辅导,家教。自己要站起来,主要还是靠自己。
可以查成绩,没有错误减三分。
全切片:l2=l1[:] 。此时发生了什么?对比l2=l1,在内存中怎么画?
列表的拼接:
l1 = l1 + l2,新创建一个列表对象,长度为l1和l2的长度之和,并且把l1绑定到新列表对象上。
l1.extend(l2),对l1就地修改,扩大长度,新增元素绑定到l2元素所绑定的对象上。
l1 += l2,和extend()是一样的,在l1原有的基础上增加长度。
增加长度时,后面的内存可能不够,这时候要整体移走。所以id()返回的是逻辑内存地址,而不是物理内存地址。
可以自己做做实验,一直extend列表,看看id是否会发生变化。体会一下内存的逻辑地址和物理地址。
列表的乘法:
l2 = l1 * 3,创建个新列表,放了3次l1的元素,最后l1指向的每个对象在l2中有3个名字指向它们。
l1 *= 3,其他的和上一个一样,只不过是就地,不创建新列表。
总结:+=和*=都是就地修改,不创建新的列表
多去理解列表在内存的存储方式,再试试列表里面嵌套列表应该怎么画内存,列表拼接、乘法、拷贝应该怎么画内存的变化。
拷贝(可以称为浅拷贝)的定义:创建一个新对象,和原来的对象“值”相同。
拷贝方法:全切片;用工厂函数(工厂函数见前几次课);copy.copy();l2 = l1 * 1A;li.copy()方法。
例如:l2 = l1[:];l2 = list(l1);l2 = copy.copy(l1);l2 = l1.copy()
总结:浅拷贝只拷贝了列表的指向,但是没有一起拷贝列表指向的对象,此时对可变对象进行操作,拷贝的对象和原列表一起发生变化。
矩阵存储:l1 = [[1,2], [3, 4]](内存中怎么画?)
numpy -> pytorch (GPU)
深拷贝:创建一个新对象,和原来的对象的“值”相同,并且与之前的对象毫无瓜葛 (彼此的改变,不会影响到对方)。
深拷贝方法:l2 = copy.deepcopy(l1)
注:深拷贝往往会创建多个对象,遇到容器对象(除str)会递归(recursive)拷贝。
思考:什么情况下,对一个对象做拷贝和做深拷贝存在差异?什么情况下没有区别?
容器嵌套时(str除外,虽然str也是容器)。
例如:列表中包含其他容器对象(除str)时才会存在深拷贝和浅拷贝的问题
列表排序:把一个列表按照一定的规则排序,一般情况是从小到大。
选择排序:每轮从左向右扫描,找到最大的数放到-1位置(-1位置指没有排序的部分末尾),这样每轮都能找到一个最大数,一共n-1次就能把列表变得有序。
冒泡排序:每轮从左向右扫描,每移动一步,就比较一下此时位置相邻两个的大小,如果前面的比后面大,就交换,这样每轮都会有个最大数冒泡到尾端。也是n-1次列表就变得有序了。
(冒泡排序的命名应该来自于一种物理现象:因为水越深水压就越高,所以气泡从水底浮出的过程中,气泡会越来越大,和冒泡排序的原理很像)
归并排序:基于分治法,每次把列表划分为两部分排序,递归到单个元素,时间复杂度很低。
大家做实验对比一下,上面三种排序算法的速度如何?
堆排序:
快速排序:
问题:什么是时间复杂度,这几个排序时间复杂度怎么样。
=== 2020.11.9 循环嵌套(break continue)、列表基础 ===
* 板书:[[:文件:2020-11-9-1.jpg]] , [[:文件:2020-11-9-2.jpg]] , [[:文件:2020-11-9-3.jpg]] , [[:文件:2020-11-9-4.jpg]] , [[:文件:2020-11-9-5.jpg]] , [[:文件:2020-11-9-6.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-8-2020.11.9.mp4 第8次理论课]
画流程图:输出前100个素数(质数)
我们需要用大循环,去寻找到100个素数,但是每找一个素数需要用一个小循环来判定当前数是否为素数。
这就是循环的嵌套。
这个程序有个问题:如果找10000个素数,找到后面会越来越慢,想想可以怎么优化。(通过列表保存前n-1个素数)
但是上述程序看起来非常复杂,如何在逻辑和流程上更加简洁呢?这里要可以用到一个模块化思维:用函数来实现内部循环。
判断一个数是否为素数,可以写一个函数,每个函数只完成一个功能。
基本数据类型、不可变对象:int, float, bool, NoneType, complex, str
什么叫基本数据类型?python自带的。不能再细分为更小的类型。这两种说法都不严谨。还是不用这个说法了。叫标量(非容器)和矢量(容器)好了。
str是一种序列,当然也是容器。
序列:
定义:(有序)、(连续存储)的容器。注意括号内的形容词。
访问方式:可以根据下标访问,常数时间内就能找到,速度极快。
列表:也是一个容器、序列,但是列表是可变对象。
创建列表对象:li = [1, 2, 3]
如何删除列表对象?这个问题本身是有问题的,没有办法直接删除列表对象。del li只是删除了li这个名字,同时取消了名字绑定。如果一个对象没有被任何名字绑定,就会被删除回收(python的垃圾回收机制)。
Q1:列表对象和其包含的对象之间有什么关系?
一个列表对象包含的其实是一堆名字,这些名字分别绑定到对应的对象上。(看一下板书)
Q2:列表中可以“包含”不同类型的对象吗? YES
列表嵌套也是可以的
Python vs. C++
在定义函数时,不需要明确声明参数的类型。执行过程中,python会动态判断参数的类型,进行相应的操作。
强类型程序语言 vs. 弱类型程序语言:这个概念比较模糊,以后不再提了。
列表对象名字绑定:l2 = l1
列表方法(method):(好多函数,自己查表)
li.append(),可以在列表后追加一个元素。例如l1.append(l2),会把l2作为一个对象追加到l1后面。
li.clear(),列表清空。
li.count()
li.index()
li.insert()
li.sort() vs. 内置函数sorted() # 仔细先学习一下,下节课会仔细讲一下
l1.extend(l2): 没有创建新的对象;l1的长度增加;l1的地址不变;l2不受影响; 增加了一些名字绑定
列表拼接(concatenation):
l3 = l1 + l2,如果l1有3个元素,l2有3个元素,l3此时只会创建一个新对象,进行了7次对象绑定。
l1.extend(l2),在l1列表的尾巴上扩展l2列表,这个操作没有新对象创建,l1地址不变,但是有3个新的名字绑定。(注意这个操作和append()是不一样的)
l1 += l2
问题:是否有新的对象创建?内存中发生了什么?in-place(就地)修改,还是新创建了一个列表对象?
列表乘法:
l2 = l1 * 3 # 发生了什么,是否有新的对象产生?
列表索引和遍历:
for i in l1: for i in range(len(l1)):
print(i) print(l1[i])
找某个位置的元素:l1[1]或者l1[-1],1是列表第二个元素,-1是列表最后一个元素。(j=i-n,此时i和j指向相同位置)
0, 1, ..., n-1 (i)
-n, -n-1, ..., -1 (j)
i = j + n
j = -(n-i) = i - n
列表的切片(slicing,把列表切成子列表):
例如:l1[2:4],返回的是列表的2号元素到3号元素的子列表,和range()一样,是前闭后开。
l1[2:9:2],返回2号元素,4号元素,6号元素,8号元素的子列表。
注:序列中,第2个元素对应着1号元素,我们是从0开始计数的。
列表的比较:
l1 is l2,两个名字是否指向一个对象。
l1 == l2,判断两个列表的值是否相等。(值的比较
l1 < l2,从左到右逐渐比较,注意数据类型,没法比较的数据类型就会报错。
成员判断:in关键字,2 in l1,即2这个值是否在l1中。(值的比较)
=== 2020.11.6 2020.11.6 循环(for while else break continue),range函数,pass语句 ===
* 板书:[[:文件:2020-11-6-1.jpg]] , [[:文件:2020-11-6-2.jpg]] , [[:文件:2020-11-6-3.jpg]] , [[:文件:2020-11-6-4.jpg]] , [[:文件:2020-11-6-5.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-7-2020.11.6.mp4 第7次理论课]
下周二上机课再来一次模拟考试,4个编程题,包括循环和列表。
8道题目:顺序,分支,循环,列表,各2道。
自学内容:做习题集会用到两个内容,都先自学一下。大学要培养自学能力。我希望在上课的过程中,教会大家如何自学,如果检验知识。授之以渔。
字符串格式化:第一次考试(编程题不会考)
模块的使用:math time random,结合dir help 百度 runoob来学习
为什么需要循环呢?
从两个例子入手,来解释。写程序之前请大家先画流程图,不断练习流程图。
例子1:写一个函数,从5个数字中选择最大的数,并返回。
def func(x1, x2, x3, x4, x5):
y = x1
if y < x2:
y = x2
if y < x3:
y = x3
...
return y
如果是100个数呢?
问题 1)100个数字如何作为参数传过去呢?100个参数?显然太多了。
问题 2)即使真的传100个参数,那么这个函数能够做的事情也太局限了,只能处理100个数字;99个数字中选择最大数,还得写另外一个函数
这两个问题,就引出了列表这种数据类型。即可以把很多数字(变长)放到列表中,传给参数。
处理很多个数字、或者长度不确定的列表,就需要(最好)用循环。否则代码会很冗余。
def func(x1, x2, x3, x4, x5):
y = x1
for x in x2, x3, x4, x5: # x2, x3, x4, x5其实被隐式的转化为一个元祖tuple对象,for循环对其进行遍历
if y < x:
y = x
return y
例子2:从一个字符串中统计一个字符(如'a')的次数。字符串类似于列表,也属于长度不定的序列,必须使用循环来遍历。
while和for都可以做。先画流程图。
循环的语法:
循环利用for和while两个关键字来操作。流程图runoob有,或者看一下板书。
https://www.runoob.com/python3/python3-loop.html
while:
形式:while condition:
code block
意义:如果满足condition这个条件,while就会执行下去
for:
形式:for var in iter:
code block
意义:var是一个变量,iter是可迭代对象,序列就属于可迭代对象(如列表,元组,字符串),var会在这个可迭代对象中循环,直到可迭代对象结束。
for循环使用起来更方便,会有隐式的遍历语句,自动增加下标和判断是否结束。
死循环:deadlock,是指循环永远不会退出来,也叫无限循环。有的时候是需要无限循环的。
如果遇到死循环,用Ctrl+C来杀死正在shell运行的程序。
遍历列表操作时,如果要删除列表元素,要非常谨慎。尤其适用for循环时,很容易出错。while循环会安全一些。
a = 0
while a < 10:
print(a)
a += 2
表格法来演练循环过程:
step a 动作
0 1 打印’1’ a+=2 (3)
1 3 打印’3’ a+=2 (5)
2 5 打印’5’ a+=2 (7)
3 7 打印’7’ a+=2 (9)
4 9 打印’9’ a+=2 (11)
5 11 退出循环
while中的else语法:
形式:while condition:
code block A
else:
code block B
意义:由于condition为False而退出循环时,才执行else。反之,如果循环由于break或return而结束,那么就不会执行else子语句。
for中的else语法:类似于while。
break:从当前循环语句中跳出(包括else一起跳了)。
continue:退出本次循环,直接进入到下一轮循环。注意,continue会在for循环中取出可迭代对象下一个值。
range函数:
range()是一个生成函数(generator,生成器;上课时我称为生成器函数,需要确认一下名称),返回range对象(range是一个类型,即这个函数也是工厂函数)。
注:生成数字序列是前闭后开的,即range(10),生成的是0, 1, 2, 3, 4, 5, 6, 7, 8, 9
例:range(15, 3, -2),以15开头,小于等于3结束,步长为-2
pass语句:
pass是一个关键字,pass语句是用来空转的,也叫空语句,占位语句。
继续做题,多做题目。
=== 2020.11.2 工厂函数,复合函数,条件控制(分支),选择表达式,做题目 ===
* 板书:[[:文件:2020-11-2-1.jpg]] , [[:文件:2020-11-2-2.jpg]] , [[:文件:2020-11-2-3.jpg]] , [[:文件:2020-11-2-4.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python-6-2020.11.2.mp4 第6次理论课]
print(),指定sep和end参数时只能通过关键字调用。
工厂函数:类型转换,根据一个给定对象,创建一个属于该类型的“新”对象。(同类型也是可以的)
例如:bool(( )) → False(空元组用括号囊括一个空格)
float(‘3e-3’) → 0.003(e是一种科学计数法,3e-3代表着3*10^-3)
注:传入工厂函数的对象要符合转换规则,complex转化为int就会返回TypeError,错误的字符串传入float会返回ValueError。
复合函数:x = int(input(‘输入一个数:’)),即函数嵌套函数,一个函数的返回值是另一个函数的传入参数。
条件控制:
形式:(请不要以过小的分辨率看以下格式,CB是code block的缩写)
if condition: | if condition1: | if condition1:
CBA | CBA | CBA
else: | elif condition2: | if condition2:
CBB | CBB | CBB
| else: | CBC
| CBC | else:
| | CBD
题目:自己画流程图,写函数。审题,注意边界条件,输入类型,返回结果要求。isinstance()可以判断类型。
判断一个数字是奇数还是偶数:偶数返回’even’,奇数返回’odd’。
判断一个年份是否为闰年(能被4整除但是不能被100整除或能被400整除):返回True或者False,传入的year为int型。
判断三个数字中的最大值:返回最大值。
传入一个三位自然数,计算并返回其百位十位个位上的数字元组,如果输入的不是三位自然数返回None。
选择表达式:x if x > y else y (其中x>y是条件判断,x和y必须是两个表达式) (注:赋值语句不是表达式)
例如:print(‘A’) if x > y else print(‘B’)
z = x if x > y else y
表达式有哪些?创建对象(理解一下)、算术运算、条件运算、逻辑运算、函数调用(返回对象)
注意:赋值语句不是表达式!
=== 2020.10.30 基本数据类型总结(标量 vs. 矢量)、bool、complex、关键字、name命名规则、工厂函数、对象可变与不可变性、内置函数(help, input, print) ===
* 板书:[[:文件:2020-10-30-1.jpg]] , [[:文件:2020-10-30-2.jpg]] , [[:文件:2020-10-30-3.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python%E7%AC%AC%E4%BA%94%E6%AC%A1%E7%90%86%E8%AE%BA%E8%AF%BE%20-%202020.10.30.mp4 第5次理论课]
* Python创建对象时的优化:整数和字符串id测试结果 [http://hlt.suda.edu.cn/LA/teach/python-2020-fall/id%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C.txt 整数和字符串测试ID] (因为浏览器汉字编码方式的不同,所以汉字部分出现了乱码。)
基本数据类型(标量scalar):
int(Python没有限制范围);float(Python不分单精度和双精度,C语言区分);str;bool(boolean);...
complex(复数):
形式:例如:1 + 2j
定义方式:例如:z = 1+2j;z = complex(a, b);z = a + b*(1j)
关键字:程序预定义的有特殊含义的名字;关键字不允许另作它用,否则执行会出现语法错误
is/ is not:用来判断两个对象是否是同一个对象。简单来说判定一下两个变量是否绑定(binding)在了同一片内存地址(当然这里涉及一些数据结构的问题,不能简单地把对象来等同于内存地址)。
注:变量名字一旦绑定,以后用到这个名字,就等同于用绑定的对象;
x和y指向相同的对象,此时 id(y) == id(x);
在Python中,对于一些整数(小于256)或字符串(简单),会共用一块地址。
del:可以销毁对象,Python中也拥有一种垃圾回收机制,定期将程序(进程)中没有任何名字指向的对象销毁。
import;and;or;not;if;else;while;for;True;False... (已讲过)
查看所有的关键字
import keyword
print(keyword.kwlist)
对象重用优化:对于一些简单的整数(<256)和字符串对象(注意整数和字符串均为不可变对象),在创建之前,会看内存中是否已有值相同的对象,如果有的话,就会用已有的,而不会重新创建新的对象。
例如
x = 123
y = 123 # 会重用上一个,而不会创建一个新的整数对象
id(x) == id(y) # x和y指向同一个对象
类似的,字符串也是一样的。bool只有两个不同的对象True和False,因此一定会重用。NoneType只有一个对象None,也一定会重用。
但是,其他类型,如浮点数、复数、列表等,就一定不会重用。
x = 0.5
y = 0.5
id(x) != id(y)
注意!!上课时走了一个弯路,找到正确的实验方法后,我也没有给出一个合理的解释。现在解释一下:
id(123456789), id(123456789)
为什么id是一样的呢?更合理的解释是:这种对象没有name绑定,因此用完就会销毁;第二个整数对象创建时,会在同一个地址上创建
name的命名规则:
1. 首位:_ a-z A-Z (注意,首位不能是数字)
2. 后续:_ a-z A-Z 0-9
工厂函数(构造函数):int;float;str;bool;list;dict;tuple;set;complex;...
既是class类型名,也是一个函数,可以制造相应对象。
标量(scalar):不可分解的,单一的。以int;float;complex; bool。
矢量(vector,也叫向量、容器container):以list;tuple;dict;set为代表
str也是容器,所以称为矢量也可以的,还可以继续分解为更小的字符串。但是str是基本数据类型,不存在更小的数据类型(如字符)。
可变对象和不可变对象:
不可变对象(Immutable Object):int;str;float;bool;complex;tuple(!);frozenset
可变对象:list;dict;set
help函数:
help(input):这个语句可以调出来帮助文档,help里可以传入函数、模块、对象、名字...
注:None代表着空数据。
input函数:(我们一般会把函数直接用input()这种方式来写,以后将直接用这种方法来代表函数)
input()会读入一个字符串,并且会剥离最后一个回车符。
例如:input: This is Python class.\n 。然后input()会返回'This is Python class.'这个字符串。
注:不可以用x = input(prompt='pls enter a number') 这种格式。理由如下:
python3.8加了新的特性,函数可以添加限定位置参数,所以使用prompt传参会报错,课上看help(input)的反斜杠就是限定符标识。详情见:https://zhuanlan.zhihu.com/p/90563819
print函数:
用法:print(value, ..., sep=' ', end='\n')
含义:一次可以print()多个数值,每个数值用'sep'分隔,print结束输出一个'end'符。
=== 2020.10.26 考试形式、IDE、简单语句、字符串、特殊字符 ===
* 板书:[[:文件:2020-10-26-1.jpg]] , [[:文件:2020-10-26-2.jpg]] , [[:文件:2020-10-26-3.jpg]] , [[:文件:2020-10-26-4.jpg]] , [[:文件:2020-10-26-5.jpg]] , [[:文件:2020-10-26-6.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python%E7%AC%AC%E5%9B%9B%E6%AC%A1%E7%90%86%E8%AE%BA%E8%AF%BE%20-%202020.10.26.mp4 第4次理论课]
2020.10.23运动会,缺一次课!
考试:
电脑阅卷,选择题30分钟20~25个题目,立刻进入编程题,3~5个题目,两个小时。
编程题要提交“.py”文件,不要用shell,文件要保存到一个可以找到的地方。
注:注意养成一个文件管理的好习惯:小心误删误覆盖;可以通过复制粘贴来版本控制;不要放桌面也不让保存的目录太深;...
考试会让你写个函数,函数名题目会给定,函数要有传入参数,有返回值。对于想拿高分的同学,要注意边界条件,要缜密思考。
写完函数,用测试语句测试,记得把测试语句注释(#)掉,要不然就用“if __name__ == 'main': ”把测试语句囊括。
PyCharm和IDLE是一个集成的开发环境(IDE:Integrated Development Environment),拥有的功能有:
编辑(edit);运行(run/execute);调试(debug)。PyCharm这学期可能不会讲。
调试方法:单步执行;print();...
简单语句:
6. 逻辑运算(Logical Operation):
Q1:operand must be True/False?NO!
Q2:return value always be True/False?NO!
例:x = 2 and 3
print(type(x))
Output:3
注:非bool型会有一个隐式转换:
对于int,0 → False
!= 0 → True
对于float 0.0 → False
!= 0.0 → True
对于str '' → False
7. 位运算(bit)
8. 优先级(priority)由高到低:
各类括号,指数(**),位运算(~; +; -),算数运算(* / % > + -),关系运算(; ==; >=; <=; !=);逻辑运算(not > and > or),赋值语句(=; -=; +=; /=; *=)
注:详情请见 https://www.runoob.com/python3/python3-basic-operators.html
复杂语句:函数定义;while;if-else;类定义;...
缩进(Indent):
为了复合语句,可以嵌套,但是不要写的过于复杂了。
4个空格或者一个TAB(制表符)为一层缩进。
注:空格和制表符不能交替使用,不过一般的IDE会自动帮你对齐缩进,并且使用一种缩进方法。
制表符不一定是8个空格,可配置,也不一定必须使用4个空格,只要文件内部是一致(consistent)的即可。
字符串(String,简称str):一串连续字符(Character,简称char)。
只考虑英文字符的话,一个字节内存存一个字符。ASCII表把字符映射成唯一数字。
“str”是Python内置(预定义提供)的基本数据类型,在Python中,char和str都属于“str”类型。
1. 定义方式:单引号('这是一个字符串');双引号("这是一个字符串");三单引号('''这是一个字符串)(有区别吗?)
2. 转义字符:
'\n'回车;'\\'反斜杠;'\t'制表符;'\b'退格符(backspace);'\a'响铃;...
3. 操作函数:
+ :一个操作符面对不同场景(操作数类型)有不同的含义,即重载(overloading)。
例:'abc' + '123' 返回 'abc123'
len():返回字符串长度。
例:len('abc\n') 的返回值为4。'\n'是一个转义字符,反斜杠(backslash)打头,代表着换行符(回车)。
写一个程序:输出当前时间,新输出的时间刷新旧时间。(提示,利用退格符,PyCharm可以,用cmd也可以,IDLE不行)
=== 2020.10.19 Python和英语的对比、简单语句 ===
* 板书:[[:文件:2020-10-19-1.jpg]] , [[:文件:2020-10-19-2.jpg]] , [[:文件:2020-10-19-3.jpg]] , [[:文件:2020-10-19-4.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python%E7%AC%AC%E4%B8%89%E6%AC%A1%E7%90%86%E8%AE%BA%E8%AF%BE%20-%202020.10.19.mp4 第3次理论课]
python(作为语言)和英语作对比,
字符:大小写字母;数字;#’’...
单词:keywords:while; def;函数名;变量名;数字;字符串。和英语语言不一样,单词可以不符合英语字典里的单词,比如'_a123'对于python也是合法的变量名
句子:statement vs sentence
段落:复合语句,文件,包 vs 节,章,篇,书
语法:非常严格(格式和语法都很严格) vs 比较随意
程序语言和英语哪个难?当然是英语,程序语言有唯一语义。
语句 (statement):
简单语句:
1. 赋值语句assignment:把一个对象(object)绑定(binding)到一个名字(name, 标识符, identifier)上。
例如:x = 7→把整数对象绑定在了x上。
注:object是内存中实际存在的东西,有4个属性(attribute):
id (identity,地址);
类型 (数据类型,类名,type,class);
数据值/内容;
方法 (method / function) (主要是class类中,详情见后面章节)。
程序执行过程中,不会有重名。
2. 函数调用:
内嵌函数 (build-in):print;abs;help;...。无需引入“包”即可使用,python默认提供。
import math:math.sqrt(); math.pow(); math.log(); ...
3. import:把一个包引入到当前文件。
4. 算数运算(Arithmetic):加 + ;减 - ;乘 * ;除 / ;整除 // ;余数 %
5. 关系运算(Relational):数字或字符串比大小,小于 < ;大于 > ;等于 == ;不等于 != 。返回bool型,即True & False。
6. 逻辑运算(Logical Operation/Calculus):and ;or ;not。
例如:3>2 and 2<1。
注:逻辑运算符号的两边不一定要是bool型,返回的结果也不一定是bool型,请自行测试学习。
注:运算注意object的type类型;注意算术符优先级;字符串比大小有个字母序(alphabetic)。
复杂语句:函数定义;while;if-else;类定义;...
=== 2020.10.16 计算机组成、数据结构、算法、流程图 ===
* 板书:[[:文件:2020-10-16-1.jpg]] , [[:文件:2020-10-16-2.jpg]] , [[:文件:2020-10-16-3.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python%E7%AC%AC%E4%BA%8C%E6%AC%A1%E7%90%86%E8%AE%BA%E8%AF%BE%20-%202020.10.16.mp4 第2次理论课]
计算机组成
冯诺依曼架构
A processing unit that contains an arithmetic logic unit and processor registers (ALU)
A control unit that contains an instruction register and program counter (CU)
Memory that stores data and instructions
External mass storage
Input and output mechanisms
https://en.wikipedia.org/wiki/Von_Neumann_architecture
https://zh.wikipedia.org/zh-hans/%E5%86%AF%C2%B7%E8%AF%BA%E4%BC%8A%E6%9B%BC%E7%BB%93%E6%9E%84
https://www.baidu.com/link?url=WUyrwd9zkEs6eVKyVR9Emg4_pkDsGxJLyrcixtszhapi6XO92QXBlbW-B8f_6dooqxiExzUKir5bCoZhZNvNefxSPO5WSIsI_E-lM2XUgSp5i2i7WY0Ip7tTSwXuy4rEsgtrYO5HOAHElbzI0P1O2mdy-jz9K4-Dx_xvd01rImKxbfrOKyOE4O7cW5U-94xh3XOvQK-8qcWUmN_EnFy2NqauxvnNXHKwWbYN9ZW5JKl8MgTi_HkZ7c6LG75yQ58UZ49MAY98NtbDAVCUXAPruPeO81ozIt36bB1jZOZRQw2PpFK7VV5euTIWOs68_D-i&wd=&eqid=e2294df70000e186000000045f7fd18c
数据和算法
计算 数据
流程图、伪代码:平方根
平方根的其他解法,更优的:https://note.youdao.com/ynoteshare1/index.html?id=828b637ef7ff73a51dd26c1bc59be3e9&type=note
=== 2020.10.12 自我介绍、大学生活学习建议、课程介绍 ===
* 板书:[[:文件:2020-10-12-1.jpg]] , [[:文件:2020-10-12-2.jpg]]
* 视频:[http://hlt.suda.edu.cn/LA/teach/python-2020-fall/Python%E7%AC%AC%E4%B8%80%E6%AC%A1%E7%90%86%E8%AE%BA%E8%AF%BE%20-%202020.10.12.mp4 第1次理论课]
自我介绍
演示几个平台
对同学的摸底,能力强的同学,不妨做我的基础编程练习,由简入繁,不断积累
大学生活、学习的几点建议
课程介绍(过程化课程)
课堂提问、上机实验(代码和报告)、期中、期末多次考试