其他复习资料
目录
一、异常处理
1.思维导图
2.常见异常示例
1)NameError。尝试访问一个未申明的变量。 >>> noname #报错。NameError: name 'noname' is not defined
(2)SyntaxError。语法错误。 >>> int a #报错。SyntaxError: invalid syntax
(3)AttributeError。访问未知对象属性。 >>> a=1 >>> a.show() #报错。AttributeError: 'int' object has no attribute 'show'
(4)TypeError。类型错误。 >>> 11 + 'abc' #报错。TypeError: unsupported operand type(s) for +: 'int' and 'str'
(5)ValueError。数值错误。 >>> int('abc') #报错。ValueError: invalid literal for int() with base 10: 'abc'
(6)ZeroDivisionError。零除错误。 >>> 1/0 #报错。ZeroDivisionError: division by zero
(7)IndexError。索引超出范围。 >>> a=[10,11,12] >>> a[3] #报错。IndexError: list index out of range
(8)KeyError。字典关键字不存在。 >>> m = {'1':'yes', '2':'no'} >>> m['3'] #报错。KeyError: '3'
3.异常处理
代码示例:
try:
f = open("testfile.txt", "w")
f.write("这是一个测试文件,用于测试异常!!")
f1 = open("testfile1.txt", "r") #报错:没有找到文件或读取文件失败
except IOError:
print("没有找到文件或读取文件失败")
else:
print("文件写入成功!")
finally:
f.close()
4.代码调试
4.1运行错误时的调试
代码示例:
>>> f = open('abc.txt') #文件或者目录不存在:FileNotFoundError
>>> a=1;b=0
>>> c=a/b #零除溢出:ZeroDivisionError
>>> 123 + 'abc' # TypeError: unsupported operand type(s) for +: 'int' and 'str'
根据Python解释器运行时抛出的异常,分别判断产生异常的原因:
第一条语句产生的FileNotFoundError表示打开不存在的文件
第三条语句产生的ZeroDivisionError表示零除错误
第四条语句产生的TypeError表示不同类型对象值不能相加
4.2逻辑错误时的调试
代码示例
import sys
n = int(sys.argv[1])
result=[]
factor = 2
while factor*factor <= n:
while (n % factor) == 0:
n //= factor
result.append(factor)
print(n, factor)
factor += 1
if n > 1:
result.append(n)
print(result)
断点跟踪、输出信息等方法
有的集成开发环境(IDE)可以设置断点,并查看变量等 通过print语句输出程序运行过程中变量值(跟踪信息),是观察和调试程序运行逻辑正确性的有效方法。
二、函数和函数式编程
1.思维导图
2.函数概述
函数的功能如下:
(1)实现结构化程序设计。通过把程序分割为不同的功能模块,可以实现自顶向下的结构化设计
(2)减少程序的复杂度。简化程序的结构,提高程序的可阅读性
(3)实现代码的复用。一次定义多次调用,实现代码的可重用性
(4)提高代码的质量。实现分割后子任务的代码相对简单,易于开发、调试、修改和维护
(5)协作开发。大型项目分割成不同的子任务后,团队多人可以分工合作,同时进行协作开发
(6)实现特殊功能。递归函数可以实现许多复杂的算法
3.函数的分类
(1)内置函数。Python语言内置了若干常用的函数,例如abs()、len()等等,在程序中可以直接使用
(2)标准库函数。Python语言安装程序同时会安装若干标准库,例如math、random等等。通过import语句,可以导入标准库,然后使用其中定义的函数
(3)第三方库函数。Python社区提供了许多其他高质量的库,如Python图像库等等。下载安装这些库后,通过import语句,可以导入库,然后使用其中定义的函数
(4)用户自定义函数。本章将详细讨论函数的定义和调用方法
4.函数的声明与调用
4.1函数的声明
基本语法如下:
代码示例:(有返回值有参数)
def my_average(a, b):
return (a+b)/2
代码示例:无返回值
def print_star(n):
print(("*"*n).center(50)) #打印n个星号,两边填充空格,总宽度50
代码示例:定义计算并返回第n阶调和数(1 + 1/2 + 1/3 + … + 1/n)的函数
def harmonic(n): #计算n阶调和数(1 + 1/2 + 1/3 + … + 1/n)
total = 0.0
for i in range(1, n+1):
total += 1.0 / i
return total
4.2函数的调用
基本语法如下:
【例8.4】函数的调用示例1(triangle.py):先定义一个打印n个星号的无返回值的函数print_star(n),然后从命令行第一个参数中获取所需打印的三角形的行数lines,并循环调用print_star()函数输出由星号构成的等腰三角形,每行打印1、3、5、... 2*lines-1个星号
import sys
def print_star(n):
print(("*"*n).center(50)) #打印n个星号,两边填充空格,总宽度50
lines = int(sys.argv[1]) #三角形行数
for i in range(1, 2*lines,2): #每行打印1、3、5、...、2*lines-1个星号
print_star(i)
例8.5】函数的调用示例2:先一个定义计算并返回第n阶调和数(1 + 1/2 + 1/3 + … + 1/n)的函数,输出前n个调和数
import sys
def harmonic(n): #计算n阶调和数(1 + 1/2 + 1/3 + … + 1/n)
total = 0.0
for i in range(1, n+1):
total += 1.0 / i
return total
n = int(sys.argv[1]) #从命令行第一个参数中获取调和数阶数
for i in range(1, n+1): #输出前n个调和数的值
print(harmonic(i))
5.参数的传递
形式参数和实际参数
声明函数时所声明的参数,即为形式参数,简称形参
调用函数时,提供函数所需要的参数的值,即为实际参数,简称实参
【例8.6】形式参数和实际参数示例(my_max1.py)
def my_max1(a, b):
if a > b: print(a, '>', b)
elif a == b: print(a, '=', b)
else: print(a, '<', b)
my_max1(1, 2)
x = 11; y = 8
my_max1(x, y)
my_max1(1)
局部变量和形式参数变量的区别在于,局部变量在函数体中绑定到某个对象;而形式参数变量则绑定到函数调用代码传递的对应实际参数对象
Python参数传递方法是传递对象引用,而不是传递对象的值
5.1传递不可变对象引用
如果函数体中修改对象的值,其结果实际上是创建了一个新的对象
【例8.7】传递不可变对象的引用示例(inc1.py):错误的递增函数如下:
i=100
def inc(j,n):
j += n
inc(i,10)
print(i)
这里在inc函数中对j进行修改值,但是没有把j return回去,因为在函数体中修改对象的值,其结果实际上是创建了一个新的对象,必须通过return回去才能把j的值赋给i,i的值才会改变。
正确的递增函数如下:
i=100
def inc(j,n):
j += n
return j
i =inc(i,10)
print(i)
5.2传递可变对象引用
调用函数时,如果传递的是可变对象(例如:list对象)的引用,则函数体中可以直接修改对象的值
【例8.9】传递可变对象引用的函数示例1:定义一个可以交换给定列表中两个指定下标的元素值的函数
def exchange(a, i, j):
temp = a[i]
a[i] = a[j]
a[j] = temp
因为list中存的是对象的引用,所以在函数里实际修改的就是被引用的值,图解如下:
5.3可选参数
我们同时也可以在声明函数时去设置参数是可选的,也就是可传可不传,不传的话会给它一个默认值
【例8.11】可选参数示例(my_sum1.py):基于期中成绩和期末成绩,按照指定的权重计算总评成绩
def my_sum1(mid_score, end_score, mid_rate = 0.4): #期中成绩、期末成绩、期中成绩权重
#基于期中成绩、期末成绩和权重计算总评成绩
score = mid_score * mid_rate + end_score * (1 - mid_rate)
print(format(score, '.2f')) #输出总评成绩,保留2位小数
my_sum1(88, 79) #期中成绩权重为默认的40%
my_sum1(88, 79, 0.5) #期中成绩权重设置为50%
5.4位置参数和命名参数
-
函数在调用时,实参默认按位置去传递形参,按位置传递的参数也称之为位置参数。
-
函数在调用时,也可以在参数列表中输入关键字去传递形参,这样就不用去顾虑位置,按指定名称传入的参数称为命名参数
-
带星号的参数后面声明的参数强制为命名参数
-
如果不需要带星号的参数,只需要强制命名参数,则可以简单地使用一个星号,如def total(initial=5, *, vegetables)
【例8.12】命名参数示例(my_sum2.py):基于期中成绩和期末成绩,按照指定的权重计算总评成绩
def my_sum2(mid_score, end_score, mid_rate = 0.4): #期中成绩、期末成绩、期中成绩权重
#基于期中成绩、期末成绩和权重计算总评成绩
score = mid_score * mid_rate + end_score * (1 - mid_rate)
print(format(score, '.2f')) #输出总评成绩,保留2位小数
#期中88,期末79,并且期中成绩权重为默认的40%。三种调用方式等价
my_sum2(88, 79)
my_sum2(mid_score = 88, end_score = 79)
my_sum2(end_score = 79, mid_score = 88)
5.5可变参数
- 在声明函数时,通过带星的参数,如*param1,允许向函数传递可变数量的实参。调用函数时,从那一点后所有的参数被收集为一个元组
- 在声明函数时,也可以通过带双星的参数,如**param2,允许向函数传递可变数量的实参。调用函数时,从那一点后所有的参数被收集为一个字典
- 带星或双星的参数必须位于形参列表的最后位置
【例8.13】可变参数示例1(my_sumVarArgs1.py)。利用带星的参数计算各数字累加和
def my_sum3(a, b, *c): #各数字累加和
total = a + b
for n in c:
total = total + n
return total
print(my_sum3(1, 2)) #计算1+2
print(my_sum3(1, 2, 3, 4, 5)) #计算1+2+3+4+5
print(my_sum3(1, 2, 3, 4, 5, 6, 7)) #计算1+2+3+4+5+6+7
【例8.14】可变参数示例2(my_sumVarArgs2.py)。利用带星和双星的参数计算各数字累加和
def my_sum4(a, b, *c, **d): #各数字累加和
total = a + b
for n in c: #元组中各元素累加和
total = total + n
for key in d: #字典中各元素累加和
total = total + d[key]
return total
print(my_sum4(1, 2)) #计算1+2
print(my_sum4(1, 2, 3, 4, 5)) #计算1+2+3+4+5
print(my_sum4(1, 2, 3, 4, 5, male = 6, female = 7)) #计算1+2+3+4+5+6+7
6.变量的作用域
全局变量、局部变量和类型成员变量
代码示例
num = 100 #全局变量
def f():
num = 105 #局部变量
print(num) #输出局部变量的值
#测试代码
f();print(num)
输出结果为105 100
类成员变量是在类中声明的变量,包括静态变量和实例变量,其有效范围(作用域)为类定义体内 在外部,通过创建类的对象实例,然后通过“对象.实例变量”访问类的实例变量,或者通过“类.静态变量”访问类的静态变量
就类似java里面的成员变量
7.递归函数
自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身
【例8.26】使用递归函数实现阶乘
def factorial(n):
if n == 1: return 1
return n * factorial(n - 1)
#测试代码
for i in range(1,10): #输出1~9的阶乘
print(i,'! =', factorial(i))
函数递归最重要的两点就是终止条件和递归步骤
8.内置函数
9.函数式编程
这部分内容比较简单,略过