理解Python迭代器/生成器
可迭代对象和迭代器
在Python中,一个对象是否可以进行迭代,取决于对象是否实现了__iter__()方法,实现了__iter__()方法的对象就是可迭代对象。
inter()和__next__()方法组成了迭代器协议,当一个对象遵循(实现)了迭代器协议时,这个对象就是迭代器对象
- iter(): 返回iterator对象本身
- next(): 返回下一项,如果已经没有可返回的项,则引发StopInteration异常
迭代器iterator统一了容器数据类型的循环遍历的标准,都可以使用for循环的方式进行遍历。
在Python中有list,tuple,set,dict这几种内置的容器数据类型,这些数据类型共同特征就是它们存储了一组数据,但它们确有不同的特性,list和tuple是有序的。set和dict,这些容器类型都是可迭代对象。它们都遵循了可迭代协议
自定义迭代器对象
from collections.abc import Iterable, Iterator
# 如果没有实现__next__()方法,那该对象仅仅是一个可迭代对象
# class Chars:
# def __init__(self):
# pass
# def __iter__(self):
# return self
# chars = Chars()
# print(isinstance(chars, Iterable)) # True
# print(isinstance(chars, Iterator)) # False
# =============================================
# 遵循了迭代器协议,实现了__iter__(),__next()__,该对象就是一个迭代器对象
# class Chars:
# def __init__(self):
# pass
# def __iter__(self):
# return self
# def __next__():
# pass
# chars = Chars()
# print(isinstance(chars, Iterable)) # True
# print(isinstance(chars, Iterator)) # True
# ==============================================
# 具体实现
class Chars:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
result = self.data[self.index]
self.index += 1
return result
for char in Chars("hello"):
print(f"char ==> {char}")
控制台输出
char ==> h
char ==> e
char ==> l
char ==> l
char ==> o
生成器
生成器提供了一种便捷实现迭代器协议的方式,有两种方式可以生成迭代器
- 生成器函数
- 生成器表达式
生成器函数
生成器函数和普通函数差不多,唯一的区别是函数内部包含了yield表达式,yield表达式可以产生一系列值提供给for循环使用或通过next()函数逐一获取。这种函数被称之为生成器函数,它返回一个生成器generator
# 普通函数
def fn():
pass
# 生成器函数
def gen_fn():
yield 1
yield "something"
gen1 = gen_fn()
print(type(gen1))
print(f"next ==> {gen1.__next__()}")
print(f"next ==> {gen1.__next__()}")
gen2 = gen_fn()
for e in gen2:
print(f"for ==> {e}")
控制台输出
<class 'generator'>
next ==> 1
next ==> something
for ==> 1
for ==> something
生成器表单达式
生成器表单式和列表推导式差不多,不过包裹的符号从[]变成()
迭代器的特性和作用
- 节省内存
- 惰性机制
- 无法反复,只能向下执行
# 普通函数
def fn():
"""
生成一万条数据后将数据返回,这样不仅消耗资源,而且同
时用于保存数据的容器也会占用大量的内存空间
"""
l = []
for e in rang(10000):
l.append(e)
return l
# 生成器函数
def gen_fn():
"""
惰性机制,调用next时才会生成
"""
for e in rang(10000):
yield e
浙公网安备 33010602011771号