迭代器
- 内部含有
_iter_
方法和_next_
方法都是迭代器
- 可迭代对象 都可以通过内置函数
iter
转换为迭代器
- 内置函数
next
进行迭代操作,当所有数据迭代完毕后,再使用 next
迭代,会抛出异常 StopIteration
。
- 使用
for
循环容器取值的都是可迭代的
容器就是将多个元素在一起的单元,并且,是可以迭代的,比如列表,字典,元组,字符串
1 2 3 4 5 6 7 8
| # 将列表转换为一个迭代器 iter_li = iter([11,22) # 通过next对迭代器进行迭代操作,每次可以迭代出来一个数据 s1 = next(iter_li) print('s1:',s1) s2 = next(iter_li) # s1 :11 print('s2:',s2) # s2 :22 s3 = next(iter_li) # StopIteration 错误
|
生成器
是一种特殊的迭代器,具备迭代器所有的特性。但其相比与迭代器,占用的内存更少
他本质上是一个函数,只不过函数的return
改为了yield
语句,正常的for
循环语句,会不停的遍历容器的对象,然后返回(如果有return的话),当我们用yield
取而代之
每当函数执行时遇到yield
时,他会记住此时的一个位置并挂起,等到使用__next__操作时,才由上一次挂起的位置继续执行。生成器不仅“记住”了它的数据状态,生成还记住了程序执行的位置
python 中定义生成器,一共有两种方式,一种是生成器表达式,另一种是生成器函数。
生成器表达式
生成器表达式的语法其实就是把列表推导式的中括号改成小括号,如下:
1 2 3 4 5 6 7
| gen_ =(item for item in range(2)) print(gen_) s1 = next(gen_) print(s1) next(gen_) next(gen_)
|
生成器函数
在函数中使用 yield
关键字可以定义一个生成器函数
1 2 3 4 5 6 7 8 9 10
| def func(): for i in range(1): yield i
gen_list = func()
gen_lsit = func() s2 = next(gen_list) print(s2) next(gen_list)
|
自定义类生成器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| from collections import Iterable from collections import Iterator import time
class Classmate(object): """定义一个同学类"""
def __init__(self): self.name = list() self.name_num = 0
def add(self, name): self.name.append(name)
def __iter__(self): return self # 返回本身
def __next__(self): if self.name_num < len(self.name): ret = self.name[self.name_num] self.name_num += 1 return ret
# 抛出异常,当循环后自动结束 else: print("-------StopIteration---") raise StopIteration
class1 = Classmate() class1.add("张三") class1.add("李四") class1.add("王五")
print("判断是否是可迭代的对象:", isinstance(class1, Iterable))
print("判断是否是迭代器:", isinstance(class1, Iterator))
for name in class1: print(name) time.sleep(1) # 结果为 判断是否是可迭代的对象: True 判断是否是迭代器: True 张三 李四 王五 -------StopIteration---
|
总结两者的区别
- 生成器就是迭代器,反之则不是
- 迭代器,在创建的时候已经生成(比如上面迭代器的列子),在需要的时候再去操作迭代器加载元素到内存中
- 而生成器,本质是一个可以暂时挂起的函数,等到需要时再继续执行去生成元素,这样子,使得生成器比迭代器更省内存。