一、迭代器
区分iterable,iterator与itertion
- itertion: 迭代,一个接一个(one after another),是一个通用的概念,比如一个循环遍历某个数组。
- iterable: 可迭代对象,能够逐一返回其成员项的对象。属于python的名词,范围也很广,可重复迭代,满足如下其中之一的都是iterable:
-
- 可以for循环: for i in iterable
- 可以按index索引的对象,也就是定义了__getitem__方法,比如list,str;
- 定义了__iter__方法。可以随意返回。
- 可以调用iter(obj)的对象,并且返回一个iterator
- iterator: 迭代器,用来表示一连串数据流的对象。重复调用迭代器的 __next__() 方法(或将其传给内置函数 next())将逐个返回流中的项。也属于python的名词,只能迭代一次。需要满足如下的迭代器协议
-
- 定义了__iter__方法,但是必须返回自身
- 定义了next方法,在python3.x是__next__。用来返回下一个值,并且当没有数据了,抛出StopIteration
- 可以保持当前的状态
定义一个 __iter__() 方法来返回一个带有 __next__() 方法的对象。创建一个返回数字的迭代器,初始值为 1,逐步递增 1
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
#输出结果
1
2
3
4
二、生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存的限制,列表的容量肯定是有限的。而且,创建一个包含100万个的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那么后面的绝大部分的元素所占用的空间都白白浪费了。那么我们是否可以在循环的过程中不断推算出后续的元素呢?这样子就不必要创建完整的list了,从而节省了大量的空间。在pythoin中,这种一边循环一边计算的机制,就是生成器。
python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
def yield_test(n):
while n > 0:
print('before yield',n)
yield n
n -= 1
print('after yield',n)
res = yield_test(3)
res.__next__()
res.__next__()
res.__next__()
#输出结果
before yield 3
after yield 2
before yield 2
after yield 1
before yield 1
生成器表达式
列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存。
列表生成器,如求10以内的奇数
num = [i for i in range(10) if i % 2]
print(num)
#输出结果
[1, 3, 5, 7, 9]
生成器表达式,形式非常类似,就是把[]换成了()。
num = (i for i in range(10) if i % 2)
print(num)
for x in num:
print(x,end = " ")
#输出结果
<generator object <genexpr> at 0x0000022789A9DEB8>
1 3 5 7 9