理解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

posted on 2024-06-02 22:23  luyifo  阅读(16)  评论(0)    收藏  举报

导航