循环设计
1、range()
利用enumerate()函数,可以在每次循环中同时得到下标和元素:
|
|
在range函数中,定义了上限、下限、和每次循环的步长
2、enumerate()
|
|
enumerate()在每次循环中,返回的是一个包含两个元素的定值表(tuple),两个元素分别赋予index和char。
3、zip()
如果有多个等长的序列,想要每次循环时从各个序列分别取出一个元素,可以利用zip()实现:
|
|
zip()函数的功能:从多个列表中,依次各取出一个元素。每次取出的(来自不同列表的)元素合成一个元组,合并成的元组放入zip()返回的列表中。
zip()函数起到了聚合列表的功能。
我们可以分解聚合后的列表:
|
|
循环对象
1、什么是循环对象
循环对象包含一个next()方法,目的是进行到下一个结果。在结束一系列结果之后,举出StopIteration错误。
当一个循环(比如for)调用循环对象时,就会在每次循环时调用next(),直到出现StopIteration,就直到循环已经结束,停止调用next()。
假设我们有一个test.txt的文件:
1234
abcd
efg
运行一下Python:
|
|
open()返回的实际上是一个循环对象,包含有next()方法。而该next()方法每次返回的就是新的一行的内容,到达文件结尾时举出StopIteration。这样,我们相当于手工进行了循环。
自动进行的话,就是:
|
|
在这里,for结构自动调用next()方法,将该方法的返回值赋予给line。循环直到出现StopIteration的时候结束。
相对于序列,用循环对象的好处在于:不用在循环还没有开始的时候,就生成好要使用的元素。所使用的元素可以在循环过程中逐次生成。这样,节省了空间,提高了效率,编程更灵活。
2、迭代器
从技术上来说,循环对象和for循环调用之间还有一个中间层,就是要将循环对象转换成迭代器(iterator)。这一转换是通过使用iter()函数实现的。
但从逻辑层面上,常常可以忽略这一层,所以循环对象和迭代器常常相互指代对方。
3、生成器
生成器(generator)的主要目的是构成一个用户自定义的循环对象。
生成器的编写方法和函数定义类似,只是在return的地方改为yield。生成器中可以有多个yield。当生成器遇到一个yield时,会暂停运行生成器,返回yield后面的值。当再次调用生成器的时候,会从刚才暂停的地方继续运行,直到下一个yield。生成器自身又构成一个循环器,每次循环使用一个yield返回的值。
下面是一个生成器:
|
|
该生成器共有三个yield, 如果用作循环器时,会进行三次循环:
|
|
再考虑如下一个生成器:
|
|
又可以写成生成器表达式(Generator Expression):
|
|
4、表推导
普通生成表方法:
|
|
表推导方式:
|
|
与生成器表达式类似,只不过用的是中括号
函数对象
1、lambda函数
普通定义函数方式:
|
|
用lambda函数的语法定义函数:
|
|
2、函数作为参数传递
|
|
可以使用上面的test函数,带入不同的函数参数:
|
|
3、map()函数
|
|
map()的功能是将函数对象依次作用于表的每一个元素,每次作用的结果储存于返回的表re中。
map通过读入的函数(这里是lambda函数)来操作数据(这里“数据”是表中的每一个元素,“操作”是对每个数据加3)。
如果作为参数的函数对象有多个参数,可使用下面的方式,向map()传递函数参数的多个参数:
|
|
4、filter()函数
它也是将作为参数的函数对象作用于多个元素。如果函数对象返回的是True,则该次的元素被储存于返回的表中。 filter通过读入的函数来筛选数据。
|
|
5、reduce()函数
reduce函数的第一个参数也是函数,但有一个要求,就是这个函数自身能接收两个参数。reduce可以累进地将函数作用于各个参数:
|
|
reduce将表中的前两个元素(1和2)传递给lambda函数,得到3。该返回值(3)将作为lambda函数的第一个参数,而表中的下一个元素(5)作为lambda函数的第二个参数,进行下一次的对lambda函数的调用,得到8。依次调用lambda函数,每次lambda函数的第一个参数是上一次运算结果,而第二个参数为表中的下一个元素,直到表中没有剩余元素。
错误处理
1、异常处理
eg:
|
|
异常处理:
|
|
语法结构如下:
|
|
流程如下:
try->异常->except->finally
try->无异常->else->finally