迭代器和生成器
迭代器和生成器
1.迭代器
1.1 迭代器类型的定义;
-
当类中定义了
__iter__
和__nxet__
两个方法。 -
__iter__
方法需要返回本身即self
-
__nxet__
方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。 -
# 创建迭代器类型 class IT(object): def __init__(self): self.counter=0 def __iter__(self): return self#返回self def __next__(self): self.counter+=1 if self.counter==3: raise StopIteration#没有数据时抛出异常 return self.counter#返回下一个数据。
1.2 迭代器对象
-
根据实例化创建一个迭代对象
-
# 根据实例化创建迭代器对象 obj1=IT() v1=next(obj1)#next内置函数直接调用,obj1.__next__() print(v1) v2=obj1.__next__() print(v2) v3=next(obj1) print(v3)# 抛出异常,因为没有值了;
-
使用for循环迭代器对象
for 循环内部在循环时,先执行
__iter__
方法,获取一个迭代对象,然后不断执行next()
取值(有异常StopIteration则循环终止)# 迭代器对象支持通过next()取值,取值结束则会自动抛出StopIteration obj=IT() for item in obj:#首先会执行obj的__iter__方法,并获取返回值,一直去反复的执行next(对象) print(item)
1.3 补充dir()函数
-
dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
-
语法
dir([object]) # 参数可以是对象、变量、类型。
-
返回值
模块的属性列表。
2.生成器
2.1 定义
-
在函数体中使用了yield的函数成为生成器(generator);
-
生成器是一种特殊的迭代器
-
在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在**下一次执行 next() **方法时从当前位置继续运行。
-
调用一个生成器函数,返回的是一个生成器对象(迭代器对象)。
-
使用生成器可以节省内存
-
def func(): print(111) yield 1 obj1=func() print(obj1)#<generator object func at 0x0000000001E2E190> # 打印的是生成器对象;
-
执行生成器函数,返回的是生成器对象
2.2 执行生成器
-
def func(): print(111) yield 1 print(222) yield 2 print(333) yield 3 obj1=func() print(obj1)#<generator object func at 0x0000000001E2E190> next(obj1)# 111 next(obj1)# 222从yield之后的位置开始执行 n1=next(obj1)# 333 print(n1)# 3 获得yield返回的值 next(obj1)# StopIteration超出范围
2.3 基于for循环执行生成器
-
data=func() for item in data: # next(data),相当于内部执行next(data) print(item)
2.4 生成器的应用场景
补充:生成器可以使用send()
给生成其中赋值;
3.可迭代对象
3.1 定义
-
如果一个类中有
__iter__
方法,返回的是迭代器对象;则我们成这个类创建的对象为可迭代对象。 -
可迭代对象是可以用来for循环的,再循环内部其实是先执行
__iter__
方法,获取迭代器对象。然后再在内部执行迭代器对象的next功能逐步取值。 -
class Foo(object): def __iter__(self): return 迭代器对象 obj=Foo() #obj就是可迭代对象 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: print(item)
-
我们使用的range函数就是可迭代对象,因为他包含了
__iter__
方法
3.2 常见的可迭代对象
-
能被for循环的数据类型都是可迭代对象;
- 字符串
- 列表
- 元组
- 字典
- 集合
3.3 判断是否是迭代器
from collections.abc import Iterator,Iterable
v1=[1,2,3]
print(isinstance(v1,Iterator)) #false 判断是否是迭代器 依据:__iter__ 和 __next__
v2=v1.__iter__()
print(isinstance(v2,Iterator))# True
# 判断可迭代
print(isinstance(v1,Iterable))# True 依据是否有__iter__且返回迭代器对象,一般和上面的判断结合使用
print(isinstance(v2,Iterable))# True
3.4 补充:isinstance函数
-
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
-
isinstance() 与 type() 区别:
- type() 不会认为子类是一种父类类型,不考虑继承关系。
- isinstance() 会认为子类是一种父类类型,考虑继承关系。
-
如果要判断两个类型是否相同推荐使用 isinstance()。
-
语法
isinstance(object, classinfo) # object -- 实例对象。 # classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。
-
返回值
如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。。
每天都是更接近成功的一天;