迭代器
可迭代对象
很多容器都是可迭代对象,此外还有更多的对象同意也是可迭代对象,但凡是可以返回一个迭代器的对象都可称之为可迭代对象。
迭代器
1.提供了一个方法,可以不断获取对象里的数据
2.用户不需要关系内部细节,只需要通过这个特点接口获取数据
3.当没有数据再次调用时,会得到一个停止标记
4.不能随机访问集合中的某个值,只能从头到尾依次访问
5.访问到一半时不能往回退
6.便于循环比较大的数据集合,节省内存
比如在python中的列表和字典容器,要想获得他里面的数据,就需要借助for…in的语法,其实for…in就是一个隐式迭代器的使用方法。
其实迭代器就是一个带状态的对象,它能在你调用next()方法时返回容器中的下一个值。
python迭代器的使用方法
iter()方法,返回一个迭代器
itertools模块函数返回的都是迭代器对象
在迭代器中会定义一个叫做__next__方法,他提供获取数据的接口;
在python中定义个next()的内置函数,专门调用迭代器的__next__方法;
一旦没有数据后,再次访问时,会受到StopIteration的异常
import itertools as it
str1 = iter('abcd')
print(next(str1))
co = it.count(10, 10) # 无限迭代器
print(next(co))
print(next(co))
print(next(co))
str2 = it.cycle('abcd') # 通过有限的元素,生成无限的迭代器
print(next(str2))
print(next(str2))
print(next(str2))
print(next(str2))
print(next(str2))
co1 = it.islice(co, 0, 1) # 从无限迭代器里面,截取有限的数据
print(next(co1))
判断一个对象是否可以迭代
使用isinstance()判断一个对象是否是iterable对象,返回值是布尔值
from collections import Iterable
print(isinstance(123, Iterable)) # False
print(isinstance('123', Iterable)) # True
自定义迭代器
任何实现了__iter__和__next__()方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器的下一个值.
可迭代对象:只要实现了__iter__方法,就是可迭代对象.
from collections import Iterable
class People(object):
"""
实现 __iter__ 实例为可迭代对象
"""
def __iter__(self):
return self
stu = People()
print(isinstance(stu, Iterable))
迭代器:获取容器中的数据,只要实现了__next__方法,就称之为迭代器.next()函数的本质就是调用对象的__next__()方法,实现了__next__()方法的对象,就是迭代器
class Man(object):
"""
实现 __next__()
实例为 迭代器
"""
def __init__(self):
self.__age = 18
def __next__(self):
self.__age += 10
return self.__age
man = Man()
print(next(man))
print(next(man))
print(next(man))
练习:
使用迭代器,来实现 斐波那契数列
class Fib(object):
def __init__(self):
self.__now = 1
self.__prev = 0
def __iter__(self):
return self
def __next__(self):
# 迭代的过程 把变量拿来使用,并且更新
value = self.__now
self.__now = self.__now + self.__prev
self.__prev = value
return value
fib = Fib()
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
生成器
利用迭代器,我们可以不断的获取数据.但是在实际开发中,我们有时候希望数据一开始不存放在内存上,而是遵循某种规律,在用户需要的时候提供给用户.这时就需要生成器,它不仅具备迭代器的能力,而且他是使用时再分配,而不是事先分配空间.
列表生成器
要创建一个生成器有很多种方法,其中最简单的就是把一个列表生成式[]改成()
li1 = [v*5 for v in range(10000)]
print(li1)
li2 = (v*5 for v in range(10000))
print(next(li2))
print(next(li2))
这种方式,被称之为列表生成器,它也是迭代器,只是书写起来会非常清晰.但列表生成器只能做一些简单的逻辑.
函数生成器
当推算算法比较复杂,用列表生成器无法实现其逻辑时,可以使用函数生成器来实现.它的语法很简单,就是将普通函数的return替换为yield
yield的意思不是返回,而是抛出后面的变量值,然后保存当前的函数状态,等待next的操作.一旦函数内部使用yield,函数名被调用是,函数的代码不会立即执行,会返回一个生成器,使用next()时,函数代码立即执行,直到遇到yield代码停止
def gen():
i = 1
while i <= 10:
return i # 函数执行return 会返回值,并停止代码的执行
i += 1
print(gen())
def gener():
i = 1
while i <= 3:
print('我是yield前面的')
yield i # 使用 yield 会返回值,并暂停代码的执行:通过 next()调用
print('我是yield后面的')
i += 1
res = gener()
print(next(res))
print(next(res))
练习
使用生成器来实现斐波拉契
def fib():
now = 1
prev = 0
while True:
value = now
now = prev + now
prev = value
yield value
f = fib()
for v in f:
print(v)