1. 迭代器
"""迭代器类型定义:
1. 类中定义了__iter__和__next__两个方法
2. __iter__方法需要返回对象本身,即:self
3. __next__方法,返回下一个数据,如果没有数据了,抛出StopIteration异常
"""
class IT(object):
"""迭代器类"""
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
# 根据类实例化创建一个迭代器对象:
obj1 = IT()
# v1 = obj1.__next__() # 1
# v2 = obj1.__next__() # 2
# v3 = obj1.__next__() # 抛出异常
print(next(obj1)) # 1 用内置函数next(),自动调用对象的__next__方法
print(next(obj1)) # 2
# print(next(obj1)) # 抛出异常
obj2 = IT()
for item in obj2: # 首先执行对象的__iter__方法并获取返回值(迭代器对象),然后反复执行next(对象)
print(item)
迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration
for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行next取值(有异常StopIteration则中止循环)
2. 生成器
- 生成器函数:是由函数+yield关键字创造出来的写法,在特定情况下,可节省内存
- 生成器函数判断标准:函数中是否存在yield关键字
- 生成器对象:执行生成器函数时,返回一个生成器对象
- 注:执行生成器函数时,函数内部代码不会执行,而是返回一个生成器对象
- next方法中放生成器对象,进入生成器函数并执行其中的代码(从上次yield返回位置继续向下执行),代码示例:
按照迭代器的定义来看,生成器也是一种特殊的迭代器类def func(): """生成器函数""" for i in range(10): yield i """创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__方法""" data = func() n1 = next(data) # 0 n2 = next(data) # 1
- 生成器补充:
- 生成器对象的send方法可往生成器对象中传参,示例:
注:生成器对象的send方法首次传参必须:生成器对象.send(None)def func(): for i in range(10): v = yield i print(v) data = func() # 创建生成器对象 n1 = data.send(None) # 首次必须send(None) # n1 = 0,此时生成器对象内执行停留在yield 0,v尚未被赋值 n2 = data.send(333) # 生成器内首先执行v赋值为333,然后执行print、进入下次循环、yield 1;此时n2 = 1
- yield from
Python3.3之后引入yield from,可在生成器中yield from另一个生成器对象
- 生成器对象的send方法可往生成器对象中传参,示例:
- 生成器特点总结:记录在函数中的执行位置,下次执行next时,从上一次的位置基础上继续向下执行
- 应用场景:需要在内存中创建很多数据时,可以基于生成器来实现一点一点生成(即用即生产),以节省内存开销
3. 可迭代对象
- 如果一个类中有__iter__方法且返回一个迭代器对象,则称这个类创建的对象为可迭代对象
class Foo(object): def __iter__(self): return 迭代器对象(生成器对象) obj = Foo() # obj是可迭代对象 # 可迭代对象是可以使用for来进行循环,在循环内部其实是先执行__iter__方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值 for item in obj: pass
- 迭代器实现可迭代对象:
class IT(object): """迭代器类""" def __init__(self): self.counter = 0 def __iter__(self): return self def __next__(self): self.counter += 1 if self.counter == 3: raise StopIteration() return self.counter class Foo(object): """可迭代对象类""" def __iter__(self): return IT() obj = Foo() # 可迭代对象 for item in obj: # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象;不断地执行迭代器对象的next方法 print(item)
- 生成器实现可迭代对象
def func(): for i in range(10): yield i class Foo(object): def __iter__(self): # 与返回生成器对象return func()效果相同 for i in range(10): yield i """ 1. 可以在__iter__方法内写入生成器函数内部的代码,不用返回任何内容,如上; 2. 也可以返回生成器对象,例如: def __iter__(self): return func() 3. 但不能直接执行生成器函数却不返回任何内容,会报错; 例如: def __iter__(self): func() # 执行生成器函数,报错 或: def __iter__(self): func # 也会报错 """ obj = Foo() for item in obj: print(item)
4. python中也有特定方法可检查迭代器对象和可迭代对象
from collections.abc import Iterator, Iterable
v1 = [11, 22, 33]
print(isinstance(v1, Iterator)) # False
print(isinstance(v1, Iterable)) # True
v2 = v1.__iter__()
print(isinstance(v2, Iterator)) # True
print(isinstance(v2, Iterable)) # True