生成器对象(自定义迭代器)
本质还是一个迭代器,只不过是自己定义迭代器,自己写来的
使用了 yield 的函数被称为生成器,跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
内部也还是只有__iter__和__next__方法
# 生成器对象也是节省存储空间的,特性与迭代器对象一致
'''
当函数体代码中含有yield关键字
第一次调用函数并不会执行函数体代码
而是将函数变成了生成器
'''
表现形式:
def index():
print('111')
yield 123
print('222')
yield 666
print(index) # <function index at 0x000001B29A8CC158>
# 没有调用之前就是一个普通的函数
# 加括号调用并接收结果:不执行代码 而是变成是生成器对象(迭代器)
res = index()
print(res) # <generator object index at 0x0000020ABA02FEB8>
# 变成生成器对象之后调用__next__就会开始执行函数体代码
print(res.__next__())
# 111
# 123
print(res.__next__())
# 222
# 666
print(res.__next__()) # 报错
'''
如果函数体代码中含有多个yield关键字,执行一次__next__返回后面的值并且让代码停留在yield位置
再次执行__next__基于上次的位置继续往后执行到写一个yield关键字处
如果没有了 再执行也会报错 StopIteration
'''
自定义range方法
# range方法其实是一个可迭代对象
for i in range(1,10)
print(i)
'''通过生成器模拟range方法'''
def my_range(start, end=None, stop=1): # 起始位置,终止位置,步长
if not end: # 如果没有给终止位置传值,则将起始位置的值给终止位置
end = start
start = 0 # 再将起始位置赋值为0
while start < end: # 循环判断
yield start # 输出start
start += stop # 相当于步长
for i in my_range(1,100,2):
print(i)
yield关键字作用
1.在函数体代码中出现,可以将函数变成生成器
2.再执行过程中,可以将后面的值返回出去,类似于return
3.还可以暂停住代码的运行
4.还可以接受外界的传值
send 关键字
# send关键字可以给yield传值,并且自动调用一次__next__方法
def my_func(name):
print(f'{name}')
while True:
s = yield
print(f'{name}和{s}')
res = my_func('tuzi')
res.__next__() # tuzi
res.__next__() # tuzi和None
res.send('jason') # tuzi和jason
# 可以给yield传值 并且自动调用一次__next__方法
生成器表达式
# 也是为了节省存储空间,主要用于后期做代码优化
语法结构:
res = (变量名 for 变量名 in 循环体代码)
"""
生成器内部的代码只有在调用__next__迭代取值的时候才会执行
"""