文章目录

  • 一、可迭代
  • 1. 可迭代的判定
  • 2. Iterable 可迭代的定义
  • 二、Iterators 迭代器
  • A. 定义
  • B. 生成迭代器iterators.__iter__()
  • C. 迭代协议
  • D. 为什么要用迭代器
  • E. 怎样制造迭代器******
  • 总结


一、可迭代

1. 可迭代的判定

# 验证是否是迭代器或可迭代
from collections.abc import Iterable,Iterator  
>>> isinstance(list(),Iterable)
True
>>> isinstance(list(),Iterator)
False
>>>

2. Iterable 可迭代的定义

可用for loop实现访问,或者是类中包含iter(),则称为可迭代。

# 自定义 iterable
from collections.abc import Iterable
class count1:
    def __init__(self, start=0):
        self.num=start
    def __iter__(self):
        return self
obj = count1(1)
print(isinstance(obj, Iterable)) # True
  1. 常见的list,tuple,dict,set,str
  2. 使用iter()后生成迭代器,也可以用next()访问
  3. 可迭代包含迭代器:即Iterable包含Iterators

二、Iterators 迭代器

A. 定义

  • 迭代中可以记忆自己的状态
  • 有__next__方法
  • 自动跳到下一个值
  • 在下一个值时更新状态
  • 结束时信号会raise StopIteration异常
  • 可用try…except来处理
itr = iter([1,2,3])
print(next(itr))
print(next(itr))
print(next(itr))
# print(next(itr)) # StopIteration

可迭代的,且有__iter__方法,即迭代器

B. 生成迭代器iterators.iter()

  1. 如果可迭代的话,则获得迭代器
  2. 如果不可迭代的话,则通过索引生成迭代器
  3. 若均不满足,就raise TypeError
  • 可用try…except来处理

C. 迭代协议

  1. __iter__()
  2. __next__() 调用next()可以不断指向下一个值
  3. 所有可迭代的都可以用**内置函数 iter()**获得迭代器,之后可以使用next()
  • 常见的list,tuple,dict,set,str,均是Iterator的子类
  • open读取后,可以用next调用

D. 为什么要用迭代器

  1. lazy:不用考虑下一个是什么,自动next
  2. 有时节省时间和内存,相对list等数据结构(见例题)
  3. 可以生成无穷长的迭代器,且占用内存很小

E. 怎样制造迭代器******

  1. 对象导向的生成器
    可以自建一个class ,包含__init__ \ iter\ next(见例子)
# 自定义 iterator
class count1:
    def __init__(self, start=0):
        self.num=start
    def __iter__(self): # 记录自己的状态
        return self
    def __next__(self): # 返回到下一个值
        self.num += 1
        return self.num
  1. 生成器函数
    自建一个def,包含yield语句,收集元素,并返回一个generator对象,即迭代器。
    其中,yield语句可以是一个或多个,通过for循环,按顺序收集迭代值(见例子)
def count2(start=0):
   num = start
   while True:
   		yield num
   		num += 1
  1. 注:
  1. 当called时,会返回迭代器但不会立即运行。
  2. 可以做一个无穷的迭代器函数,要比对象导向的更简洁
  1. 生成器的表达式
    自建一个类似list的表达式 (x for x in L).
L = list(range(1,11))
cubes = (x**3 for x in L)
  1. 注:
  1. 类似于for loop加append
  2. 比生成函数更简洁

总结

  1. 迭代器和可迭代的不同点是,迭代中是有属性next+iter,而可迭代中有iter或getitem
  2. 不同生成器的简洁性:表达式 > 函数 > 表达式
  3. return 和yield的比较
  • return
    函数的终点、返回值或者None、摧毁了所有的局部变量
  • yield
    暂停函数的执行、获取值不摧毁局部变量、之后会从停下来的地方接着运行