Files
python/20-24/lianxi-Iterator.py
2026-05-06 11:21:42 +08:00

192 lines
5.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 手动实现一个自定义迭代器
# 我们可以通过定义一个类并实现__iter__()和__next__()方法来创建一个自定义的迭代器。
class MyCustomIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
my_inter_instance = MyCustomIterator([1, 2, 3])
for item in my_inter_instance:
print(item)
# 再次尝试遍历同一个迭代器实例,会发现它已经耗尽
print("\n--- 再次遍历已耗尽的自定义迭代器 ---")
# 没有任何输出,此时my_inter_instance迭代器已耗尽
for item in my_inter_instance:
print(item)
# 迭代器
class MyCustomIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
# 可迭代对象
# Iterable 可迭代对象:实现了__iter__()方法,每次都都会返回一个新的Iterable 实例
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
return MyCustomIterator(self.data)
# 可以遍历多次
print("\n--- 可以遍历多次 ---")
my_interbale = MyIterable([1, 2, 3])
# 第一次遍历
print("第一次遍历")
for item in my_interbale:
print(item)
# 第二次遍历
print("第二次遍历")
for item in my_interbale:
print(item)
# 验证每次iter()都会创建新的Iterator
print("验证每次iter()都会创建新的Iterator")
iterable = MyIterable([1, 2, 3])
it1 = iter(iterable)
it2 = iter(iterable)
print(f"两个Iterator是否是同一个对象{it1 is it2}") # False
print(f"it1: {list(it1)}")
print(f"it2: {list(it2)}")
# Generator (生成器)
# 5.1 概念与特点
# 生成器是Python中的一种特殊类型的迭代器,它允许你在迭代过程中逐渐生成值,而不是一次性生成所有的值。生成器由函数创建,这些函数使用yield关键字而不是return来返回值。
# 基本特点:
# 惰性求值:只在需要时才生成值,节省内存
# 状态保持:函数在yield后暂停,保持内部状态
# 迭代器协议:遵循Python的迭代器协议
# 内存友好:特别适合处理大数据集
# 代码简洁:比手动实现迭代器更简洁
# 生成器函数
def simple_gen():
yield 1
yield 2
yield 3
gen = simple_gen()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
try:
print(next(gen))
except StopIteration:
print("生成器函数耗尽,没有更多值")
def num_generator():
yield 1
yield 2
yield 3
yield 4
yield 5
gen = num_generator()
# 通过for循环生成器,会自动调用next()进行执行
for num in gen:
print(num)
# yield关键字的工作原理
# yield是Python中用于创建生成器函数的一个关键字。与return语句类似,它也可以从函数返回值,但不同之处在于:
# 当函数执行到yield语句时,它会暂停执行并将yield后的值返回给调用者
# 函数的状态(包括局部变量和指令指针)会被保存下来
# 在下次调用时从暂停的地方继续执行,而不是像return那样彻底退出函数
# 生成器表达式
# 除了生成器函数,Python还支持生成器表达式。它们与列表推导式(list comprehensions)语法类似,但使用圆括号()而不是方括号[],并且返回的是一个生成器对象,而不是一个完整的列表。
# 生成器在处理数据时具有显著的优势:
# 内存效率高:生成器采用"惰性评估"lazy evaluation)机制,不会立即将所有元素生成并存储在内存中,而是按需生成
# 处理大数据流:非常适合处理网络数据流、文件读取等场景,因为数据可以逐块处理
# 基本语法
print("生成器表达式")
my_gen = (x**2 for x in range(5))
print(f"{type(my_gen)}") # <class 'generator'>
for item in my_gen:
print(item)
# 高级特性
# 双向通信 (send()方法)
# 生成器不仅可以向调用者返回值,还可以通过send()方法从调用者接收值。这使得生成器能够实现更复杂的协程(coroutine)行为。
# 定义一个支持双向通信的生成器函数
def double_yield():
# 第一个yield会暂停并等待外部send()发送值,将接收到的值赋给x
# 注意:第一次启动生成器时,next()或send(None)会使这个yield接收None
x = yield
# 进入无限循环,持续进行双向通信
while True:
# 暂停并返回x * 2的值,同时等待外部send()发送新的值给x
x = yield x * 2
gen = double_yield()
next(gen) # 启动生成器
print(gen.send(10))
print(gen.send(2))
# 异常处理 (throw()和close()方法)
# 生成器提供了其他方法来控制其生命周期和行为:
def exception_hanlding_generator():
try:
while True:
yield "正在运行中"
except GeneratorExit:
print("生成器关闭")
finally:
print("生成器清理完成")
gen = exception_hanlding_generator()
print(next(gen))
gen.close()