028—迭代器和生成器
作者:互联网
什么是可迭代对象:
python中的所有存在的都是对象,如果对象有 __iter__方法,那么该对象就是可迭代对象
可以通过 dir(obj) 方法来查看对象所拥有的方法
t = ('a','b')
print(dir(t))
# ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
通过成员运算符 in 来判断对象是不是可迭代对象
name = 'bone'
age = 18
li = [1,3,4]
t = ('a','b')
d = dict()
s = {1,2}
print('__iter__' in dir(name)) # True
print('__iter__' in dir(age)) # False
print('__iter__' in dir(li)) # True
print('__iter__' in dir(t)) # True
print('__iter__' in dir(d)) # True
print('__iter__' in dir(s)) # True
可迭代对象能够将其所有的内容一次性展示,所有它比较占内存,而且可迭代对象是不能直接循环取值的
学习循环时使用for执行循环了可迭代对象,其实内部是将可迭代对象先转换成了迭代器,然后循环取值的
for i in 'name':
print(i)
迭代器
通过名字可以理解,它就是一个用于迭代的器具
什么是迭代器
- 如果对象具有 iter 和 next 方法,那么它就是一个迭代器
- 可以说迭代器肯定是一个可迭代对象,但是可迭代对象不一定是迭代器
- 上面的可迭代对象都不迭代器
name = 'bone'
age = 18
li = [1,3,4]
t = ('a','b')
d = dict()
s = {1,2}
print('__next__' in dir(name)) # False
print('__next__' in dir(age)) # False
print('__next__' in dir(li)) # False
print('__next__' in dir(t)) # False
print('__next__' in dir(d)) # False
print('__next__' in dir(s)) # False
可迭代对象能够转换成迭代器
通过 iter() 方法 或者 iter() 方法可以将一个可迭代对象转换为迭代器(iterator)
name = 'bone'
iteobj = iter(name)
print(iteobj)# <str_iterator object at 0x7f7f578a0040>
li = [1,3,4]
iteobj = li.__iter__()
print(iteobj)# <list_iterator object at 0x7ff7a4143850>
迭代器有什么用处
比如一个列表,存储了几千万的数据,想要查看这个列表,直接将其读取打印,那么会非常的占内存
再比如一个生活中的例子,一个文档或者Excel表格,特别大,当打开他们时,就会造成电脑变得很卡,甚至死机
有了迭代器的话就不一样了,可以一点一点的读取内容,当你读取第二个内容时,第一个内容就从内存消失了,这样就节省了内存消耗
使用迭代器
想要从迭代器取值,需要使用它的 next 方法,每执行一次, 就取出一个值
name = 'bone'
iteobj = iter(name)
print(iteobj)# <str_iterator object at 0x7f7f578a0040>
print(iteobj.__next__())
print(iteobj.__next__())
print(iteobj.__next__())
print(iteobj.__next__())
# b
# o
# n
# e
上面执行了4次__next__()方法,所有元素已经都取到了,如果再执行一次就会报错,要处理这个就需要自己去捕获处理了
print(iteobj.__next__())
# print(iteobj.__next__())
# StopIteration
for循环和迭代器
for循环实际上就是将可迭代对象转成迭代器,然后执行__next__()方法,但是当它执行发现有 StopIteration 时,会处理这个异常
总结::
1、节省内存,进入下次迭代内容后,上一次的会从内存释放
2、它只能一直迭代向前,不能后退
3、无法知道迭代器中有多少个对象,只能等到抛出异常才知道
生成器
生成器其实可以叫做生成迭代器,它是本质就是个迭代器,也有 iter 和 next 方法
创建生成器
一个函数如果有 yeild 关键字,那么它就是个生成器
def func(list_num):
i = 0
while i<len(list_num):
yield list_num[i]
i += 1
g = func([1,3,4,2,5]) # <generator object func at 0x7f808705fac0>
print('__iter__' in dir(g)) # True
print('__next__' in dir(g)) # True
生成器获取值:
生成器对象使用next() 或者 next()方法就可以取值
print(g.__next__()) # 1
print(next(g)) # 3
同样,超出后会报错
print(g.__next__()) # 1
print(next(g)) # 3
print(next(g)) # 4
print(next(g)) # 2
print(next(g)) # 5
print(next(g))
# Traceback (most recent call last):
# print(next(g)) # 3
# StopIteration
当然也可以for循环,因为它是迭代器
for i in g:
print(i)
# 1
# 3
# 4
# 2
# 5
yield关键字
yield会返回一个值,这点和return一样,区别就是return会终止函数,但是yield不会,它会记录着状态并返回
return函数内只能有一个,但是yelid可以有多个
def func(list_num):
i = 0
while i<len(list_num):
yield 1
yield 2
yield 3
i += 1
g = func([1,3,4,2,5])
print(next(g)) # 1
print(next(g)) # 2
print(next(g)) # 3
print(next(g)) # 1
print(next(g)) # 2
send方法
通过next方法可以获取yield的值,send也可以,send还有一个功能就是给yelid传值
这里直接使用send报错,提示不能把不是None的值发送到刚启动的生成器
def func(list_num):
i = 0
while i<len(list_num):
s = yield 1
print(s)
i += 1
g = func([1,3,4,2,5]) # <generator object func at 0x7f808705fac0>
print(g.send('a')) # TypeError: can't send non-None value to a just-started generator
print(g.send('a'))
发送个None试一下
可以发现,s被赋值了’a’,这说明 yield 接收到了这个值,并赋值给了s
def func(list_num):
i = 0
while i<len(list_num):
s = yield 1
print(s)
i += 1
g = func([1,3,4,2,5]) # <generator object func at 0x7f808705fac0>
print(g.send(None))
print(g.send('a'))
# 1
# a
# 1
不send(None),先next一下再send值也可以
def func(list_num):
i = 0
while i<len(list_num):
s = yield 1
print(s)
i += 1
g = func([1,3,4,2,5]) # <generator object func at 0x7f808705fac0>
print(next(g))
print(g.send('a'))
# 1
# a
# 1
yelid…from
上面通过循环拿到列表的元素并且yield返回,这个操作可以通过 yield…from来实现
# yield list_num返回的是整个列表
def func(list_num):
yield list_num
g = func([1,3,4,2,5])
print(next(g)) # [1, 3, 4, 2, 5]
# yield from list_num 返回每个元素
def func(list_num):
yield from list_num
g = func([1,3,4,2,5])
print(next(g)) # 1
print(next(g)) # 3
print(next(g)) # 4
标签:__,迭代,生成器,iter,next,print,028,dir 来源: https://blog.csdn.net/c_first/article/details/113704825