本节内容
1.迭代器&生成器
2.装饰器
a) 基本装饰器
b)多参数装饰器
3.递归
4.算法基础:二分查找,二维数组转换
5.正则表达式
6.常用模块学习
7.作业:计算器开发
a)实现加减乘除及括号优先级解析
b)用户输入1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实计算器所得出的结果一致
迭代器&生成器
迭代器
迭代器是访问集合元素的一种方式。迭代对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代器途中后退。
特点:
- 访问者不需要关心迭代器内部的结构,仅通过next()方法不断去取下一个内容
- 不能随机访问集合中的某个值,只能从头到尾依次访问
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
对于原生支持随机访问数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势、反而丢失了索引值(可以使用内建函数enumerate()找回索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
另外,迭代器的一代优点是不要求事先准备好整个迭代过程中所有的元素。迭代器激进在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁,这个特点使它特别适合用于遍历一些巨大的或是无限的集合。比如几个G的文件,或是斐波那契数列等等,
迭代器更大的功劳是提供了一个统一的访问集合的接口,只要定义了__iter__方法对象,就可以使用迭代器访问。
迭代器有两个基本方法
- next方法:返回迭代器的下一个元素
- __iter__方法:返回迭代器对象本身
生成一个迭代器:
a = iter([1,2,3,4,5])
print(a.__next__())
print(a.__next__())
print(a.__next__())
print(a.__next__())
print(a.__next__())
print(a.__next__())
当调取一个不存在的值时会报错
Traceback (most recent call last):
File "D:/Users/Administrator/PycharmProjects/练习/函数/test.py", line 8, in <module>
print(a.__next__())
StopIteration
Process finished with exit code 1
了解了StopIteration,可以使用迭代器进行遍历了
1 lst = range(5) 2 it = iter(lst) 3 try: 4 while True: 5 val = it.__next__() 6 print (val) 7 except StopIteration: 8 pass
下面用生成斐波那契数列为例子,说明为何用迭代器
代码一
1 def fab(max): 2 n, a, b = 0, 0, 1 3 while n < max: 4 print (b) 5 a, b = b, a + b 6 n = n + 1 7 fab(10)
直接在函数fab(max)中用print打印会导致函数的可复用性变差,因为fab返回None。其他函数无法获得fab函数返回的数列
代码二
1 def fab(max): 2 L = [] 3 n, a, b = 0, 0, 1 4 while n < max: 5 L.append(b) 6 a, b = b, a + b 7 n = n + 1 8 return L
代码二满足了可复用性的需求,但是占用了内存空间,最好不要。
代码三
for i in range(1000): pass
for i in xrange(1000): pass
对比前一个返回1000个元素的列表,而后一个在每次迭代中返回一个元素,因此可以使用迭代器来解决复用可占空间的问题
1 class Fab(object): 2 def __init__(self, max): 3 self.max = max 4 self.n, self.a, self.b = 0, 0, 1 5 6 def __iter__(self): 7 return self 8 9 def next(self): 10 if self.n < self.max: 11 r = self.b 12 self.a, self.b = self.b, self.a + self.b 13 self.n = self.n + 1 14 return r 15 raise StopIteration()
生成器
带有yield的函数在pthon中被称为generator(生成器),举几个例子说明下(还是用生成斐波那契数列说明)
可以看出代码3没有代码1简洁,生成器(yield)可记忆保持代码1的简洁性,又可以保持代码3的效果
代码四
1 def fab(max): 2 n, a, b = 0, 0, 1 3 while n < max: 4 yield b 5 a, b = b, a + b 6 n = n + 1 7 for n in fab(5): 8 print(n)
简单的讲,yield的作用就是把一个函数变成一个generator,带有yield的函数不再是一个普通函数,Python解释器
会将其视为一个generator,调用fab(5)不会执行fab函数,而是返回一个iterable对象!在for循环执行时,每次循环
都会执行fab函数内部的代码,执行到yield b时,fab函数就返回一个迭代值,下次迭代时,代码从yield b的下一条语句
继续执行,而函数的本地变量看起来和上次终端执行前是完全不一样的,于是函数继续执行,直到再次遇到yield。看起来
就好像一个函数在正常执行的过程中被yield中断了数次,每次中断都会通过yield返回当前的迭代值。
也可以手动调用fab(5)的next()方法(因为fab(5)是一个generator对象,该对象具有next()方法),这样
我们就可以更清楚地看到fab的执行流程。