可迭代对象
可迭代对象(Iterable),就是任意定义了一个可以返回迭代器的__iter__
方法的对象。
常见的数据类型如列表、元组、字符串等,都属于可迭代对象。
from collections import Iterable
print(isinstance([1, 2, 3], Iterable)) # True
print(isinstance({1, 2, 3}, Iterable)) # True
print(isinstance((1, 2, 3), Iterable)) # True
print(isinstance(100, Iterable)) # False
可迭代对象用于for
循环:
from collections import Iterable
class A():
def __init__(self):
self.arrs = [3, 6, 9]
def __iter__(self):
return iter(self.arrs)
for i in A():
print(i, end=' ') # 3 6 9
print('')
print(isinstance(A(), Iterable)) # True
class B():
def __init__(self):
self.arrs = [3, 6, 9]
def __getitem__(self, item):
return self.arrs[item]
for i in B():
print(i, end=' ') # 3 6 9
print('')
print(isinstance(B(), Iterable)) # False
迭代器
迭代器(Iterator),就是任意定义了__iter__
和__next__
方法的对象。
使用__iter__
方法将一个可迭代对象转换成迭代器。
from collections import Iterator
print(isinstance([1, 2, 3], Iterator)) # False
print(isinstance(iter([1, 2, 3]), Iterator)) # True
使用__next__
方法不断调用并返回下一个值,直到最后抛出StopIteration
异常。
from collections import Iterable, Iterator
class C():
def __init__(self):
self.n = 0
self.arrs = [3, 6, 9]
def __next__(self):
if self.n < len(self.arrs):
value = self.arrs[self.n]
self.n += 1
return value
else:
raise StopIteration
def __iter__(self):
return self
i = C()
print(next(i)) # 3
print(next(i)) # 6
print(next(i)) # 9
print(next(i)) # Error: StopIteration
print(isinstance(C(), Iterable)) # True
print(isinstance(C(), Iterator)) # Ture
生成器
生成器(Generator),只需任意方法中包含关键字yield
。
生成器也是一种迭代器,它特殊的地方在于函数体中没有return
关键字,函数的返回值是一个生成器对象。
函数每次运行到yield
时,会暂停并保存当前运行状态,返回数值,并在下一次执行next
方法时,从保存位置继续往下执行。
from collections import Iterable, Iterator, Generator
def gen():
yield 3
yield 6
yield 9
i = gen()
print(isinstance(i, Iterable)) # True
print(isinstance(i, Iterator)) # True
print(isinstance(i, Generator)) # True
for x in i:
print(x, end=' ') # 3 6 9
# yield from 的写法
def gen2():
yield from [3, 6, 9]
生成器表达式
a = (x for x in range(10))
print(a) # <generator object <genexpr> at 0x0000023508C30B48>
b = [x for x in range(10)]
print(b) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
生成器适用场景:不必将所有数据一次性加载到内存当中,只有当具体使用时(如调用__next__
方法)才生成值,可以节省资源。