文章目录
迭代对象,迭代器,生成器
-
若对象中实现了
__getitem__
或者__iter__
方法,那么这个对象就是可迭代对象 -
若对象中实现了**
__next__
和__iter__
方法**,那么这个对象就是迭代器 -
可迭代对象的背后其实是迭代器在起作用
使用了 yield 的函数被称为生成器(generator)
yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。
然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。
调用一个生成器函数,返回的是一个迭代器对象。可以说所有生成器对象都是迭代器对象,有一点细微的区别:
- 生成器对象更倾向于在无限中集合中惰性的输出需要的数据
- 迭代器更倾向于在实现已知道所有数据的情况下惰性输出需要的数据
恰当的例子就是斐波那契数列,可以用生成器实现一个斐波那契数列,但因为该数列的元素是无限多个,所以说其是迭代器实现的就没有说由生成器实现的说法恰当。
判断对象是否是可迭代对象的方法
方法一:
print('__iter__' in dir([1, 2, 3])) # True
方法二:
from collections.abc import Iterable
print(isinstance('123', Iterable)) # True
arr = [1, 2, 3]
arr_iter = arr.__iter__()
print(arr_iter.__next__()) # 1
# arr是可迭代对象, 不是迭代器
print('__next__' in dir(arr)) # False
# arr_iter是迭代器
print('__next__' in dir(arr_iter)) # True
1. __iter__()
该方法返回的是当前对象的迭代器类的实例。因为可迭代对象与迭代器都要实现这个方法,因此有以下两种写法。
- 用于可迭代对象类的写法,返回该可迭代对象的迭代器类的实例。
- 用于迭代器类的写法,直接返回self(即自己本身),表示自身即是自己的迭代器。
2. __next__ ()
返回迭代的每一步,实现该方法时注意要最后超出边界要抛出StopIteration
异常。
def __init__(self, start, end):
self.start = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.start < self.end:
self.start += 1
return self.start - 1
else:
raise StopIteration
for i in MyRange(1, 3):
print(i) # 1 2
for i in range(1, 3):
print(i) # 1 2
3. iter(source, sentinel=None)
def iter(source, sentinel=None): # known special case of iter
"""
iter(iterable) -> iterator
iter(callable, sentinel) -> iterator
Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.
"""
pass
Example 1:
it = iter([1, 2, 3, 4, 5])
def func():
return next(it)
for j in iter(func, 4):
print(j)
# 1
# 2
# 3
Example 2:
class Next:
def __init__(self):
self.data = [0, 1, 2, 3, 4]
self._iter = iter(self.data)
def get_len(self):
return len(self.data)
def __iter__(self):
print('iter')
return self
def __call__(self):
print("call")
return next(self._iter)
def __next__(self):
print('i am next')
return next(self._iter)
这里Next()
是初始化创建一个实例,该实例可以被调用,也就是Next()()
时会调用Next().__call__()
。
而iter
对象的第一个参数如果是可调用对象时,会一直调用该对象直到与第二个参数相同或者**raise StopIteration
**
而每次执行__call__
时,会对self._iter
迭代一次。这里__next__
和__iter__
没有执行。
for it in iter(Next(), 6):
print(it)
# call
# 0
# call
# 1
# call
# 2
# call
# 3
# call
# 4
# call
iter_next = iter(Next())
print("===================")
for it in iter_next:
print(it)
# iter
# ===================
# iter
# i am next
# 0
# i am next
# 1
# i am next
# 2
# i am next
# 3
# i am next
# 4
# i am next