Python之路,Day4

本节内容

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) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实计算器所得出的结果一致

迭代器&生成器

 

 

迭代器

迭代器是访问集合元素的一种方式。迭代对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代器途中后退。

特点:

  1. 访问者不需要关心迭代器内部的结构,仅通过next()方法不断去取下一个内容
  2. 不能随机访问集合中的某个值,只能从头到尾依次访问
  3. 访问到一半时不能往回退
  4. 便于循环比较大的数据集合,节省内存

   对于原生支持随机访问数据结构(如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
View Code

 

下面用生成斐波那契数列为例子,说明为何用迭代器

代码一

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)  
View Code

直接在函数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
View Code

代码二满足了可复用性的需求,但是占用了内存空间,最好不要。

代码三

 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()
View Code

生成器

  带有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)
View Code

  简单的讲,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的执行流程。

原文地址:https://www.cnblogs.com/allen-zhang/p/6086512.html