Python》》迭代器、可迭代对象 、生成器 yield 生成器表达式
迭代器 Iterator
迭代器是一种对象,该对象包含值的可计数数字。
迭代器是可迭代的对象,这意味着您可以遍历所有值。
从技术上讲,在 Python 中,迭代器是实现迭代器协议的对象,它包含方法 iter() 和 next()。
str = 'abcd'
print(str)
it = iter(str)
print(it)
print(next(it))
print(next(it))
## 结果
abcd
<str_ascii_iterator object at 0x00000000015AC4C0>
a
b
mytuple = ("apple", "banana", "cherry")
# 返回一个迭代器
myit = iter(mytuple)
print(next(myit))
print(next(myit))
print(next(myit))

class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)
可迭代对象 Iterable
## for 循环实际上创建了一个迭代器对象,并为每个循环执行 next() 方法。
mystr = "banana"
for x in mystr:
print(x)


from collections.abc import Iterable, Iterator
# 列表是可迭代对象,但不是迭代器
my_list = [1, 2, 3]
print(isinstance(my_list, Iterable)) # True
print(isinstance(my_list, Iterator)) # False
# 获取迭代器
my_iter = iter(my_list)
print(isinstance(my_iter, Iterator)) # True
# 使用迭代器
print(next(my_iter)) # 1
print(next(my_iter)) # 2
print(next(my_iter)) # 3
# print(next(my_iter)) # StopIteration
# 迭代器只能遍历一次
list2 = [1, 2, 3]
iter2 = iter(list2)
for i in iter2:
print(i) # 打印 1,2,3
# 再次遍历将没有任何输出
for i in iter2:
print(i) # 无输出
# 自定义可迭代对象
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
return MyIterator(self.data)
# 自定义迭代器
class MyIterator:
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
value = self.data[self.index]
self.index += 1
return value
# 使用
my_iterable = MyIterable([1, 2, 3])
for item in my_iterable:
print(item) # 1 2 3

可迭代对象不一定是迭代器
# 列表、集合、字符串、元组 是可迭代对象,但不是迭代器
# 列表 - 可迭代对象,但不是迭代器
my_list = [1, 2, 3, 4, 5]
print(type(my_list)) # <class 'list'>
# 可以 for 循环
for i in my_list:
print(i)
# 但不能直接使用 next()
# next(my_list) # TypeError: 'list' object is not an iterator
# 需要转换为迭代器才能使用 next()
list_iterator = iter(my_list)
print(next(list_iterator)) # 1
生成器
生成器是 Python 中一种特殊的迭代器,允许你逐个生成值,而不是一次性返回所有结果,从而节省内存。
》》生成器表达式 类似列表推导式,但使用圆括号:
num = [x for x in range(5) ] # 列表推导式,元组没有推导式
li = (x for x in range(5)) # 列表推导式的【】 改成(),就是生成器表达式
print(num)
print(li)
print(next(li))
print(next(li))
print(next(li))
## 结果
[0, 1, 2, 3, 4]
<generator object <genexpr> at 0x0000000001386080>
0
1
2
# 列表推导式(立即创建所有值)
list_squares = [x**2 for x in range(10)] # 占用内存
# 生成器表达式(惰性求值)
gen_squares = (x**2 for x in range(10)) # 几乎不占内存
# 使用生成器
for square in gen_squares:
print(square)
# 转换为列表(如果需要)
squares_list = list(gen_squares)
》》生成器函数 使用 yield 关键字定义:
生成器函数:函数体中如果出现了 yield 关键字,那该函数就是 生成器函数
生成器对象:调用 生成器函数 时,其函数体不会立刻执行,而是返回一个 生成器对象写在 生成器函数中的代码,需要通过 生成器对象 来执行
1、调用 生成器对象的 生成器对象.next 方法 或 next(生成器对象) ,会让 生成器函数中的代码开始执行。
2、当生成器函数中的代码开始执行后,遇到 yield 会 “暂停”执行,并且其内部会记录“暂停”的位置。
3、后续调用 生成器对象.next() 或 next(生成器对象),都会从上一次“暂停”的位置,继续执行,直到再次遇到 yield。
4、遇到 return会抛出 stopIteration 异常,并将 return 后面的表达式,作为异常信息。
5、yield 后面所写的表达式,会作为本次 next() 或 next() 方法的返回值
# 基本生成器函数
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
# 使用生成器 生成器是特殊的迭代器,迭代器一定是可迭代对象。反之就不一定
for num in count_up_to(5):
print(num) # 输出: 1 2 3 4 5
# 或者手动迭代
counter = count_up_to(3)
print(next(counter)) # 1
print(next(counter)) # 2
print(next(counter)) # 3
# print(next(counter)) # StopIteration 异常

yield from 能把一个 可迭代对象 里的东西依次 yield 出去 =>代替 for + yield
def demo():
nums=range(1,6)
for num in nums:
yield num
for num in demo():
print(num)
###############################
def demo2():
nums = range(1, 6)
yield from nums
for num in demo2():
print(num)
# 生成器.send(值) 可以让生成器继续执行的同时,给上一次 yield 传值
# 备注1: next 只能取值,send 既能取值,也能送值
# 备注2:第一次启动生成器,不能传值
# 它允许你向生成器内部发送值,这个值会成为生成器中当前暂停的 yield 表达式的返回值。
def demo():
print('AAAAAA')
a = yield "===AAA====="
print(a)
print('BBBBBB')
b= yield "=====BBBB====="
print(b)
print('cccccc')
yield "=====CCCC====="
d = demo()
print(next(d))
print(d.send('zenzenzenzen'))
print(next(d))
=====结果====
AAAAAA
===AAA=====
zenzenzenzen
BBBBBB
=====BBBB=====
None
cccccc
=====CCCC=====
生成器表达式
无论是迭代器、还是生成器对象,都可以用list、tuple、set等直接拿到其里面的所有内容(注意:如果数据量很大,很占内存的,容易挤爆内存)
当 每个结果,只依赖当前这一个元素 。不依赖前后元素
nums = [10,20,30]
# 列表推导式 [表达式 for 变量 in 可迭代对象]
v01 = [n*2 for n in nums]
print(v01)
# 生成器推导式 (表达式 for 变量 in 可迭代对象)
v02 = (n * 2 for n in nums)
print(v02) # v02 是生成器对象
print(list(v02))
v03 = (n * 2 for n in nums)
for n in v03:
print(n)
结果
[20, 40, 60]
<generator object <genexpr> at 0x000000000142A9B0>
[20, 40, 60]
20
40
60
生成器 (Generator) vs 迭代器 (Iterator) VS 可迭代对象
迭代器是一个更广泛的概念,而生成器是创建迭代器的一种简便方式。
class MyIterator:
"""手动实现的迭代器"""
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 # 手动抛出异常
value = self.data[self.index]
self.index += 1
return value
# 使用迭代器
it = MyIterator([1, 2, 3])
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# print(next(it)) # StopIteration
def my_generator(data):
"""生成器函数,自动处理迭代状态"""
for item in data:
yield item # 自动暂停和恢复
# 使用生成器
gen = my_generator([1, 2, 3])
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
# print(next(gen)) # StopIteration 自动抛出
>>>迭代器:可能占用较多内存
class FileLineIterator:
"""文件行迭代器 - 一次加载所有行"""
def __init__(self, filename):
# 一次加载所有行到内存
with open(filename, 'r') as f:
self.lines = f.readlines()
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.lines):
raise StopIteration
line = self.lines[self.index]
self.index += 1
return line
>>>>>生成器:惰性求值,内存效率高
def file_line_generator(filename):
"""文件行生成器 - 逐行读取,内存友好"""
with open(filename, 'r') as f:
for line in f:
yield line # 一次只处理一行
# 处理大文件时内存效率极高
for line in file_line_generator('huge_file.txt'):
process(line) # 一次只处理一行
更多推荐



所有评论(0)