192 lines
5.3 KiB
Python
192 lines
5.3 KiB
Python
# 手动实现一个自定义迭代器
|
||
|
||
# 我们可以通过定义一个类并实现__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()
|