yield(自定迭代器)

若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值是一个生成器对象也叫自定义迭代器

def index():
    print('Hello World_1')
    yield 'hhhh_1'
    print('Hello World_2')
    yield 'hhhh_2'


print(index)  # 普通函数
# <function index at 0x7fd9168c5ea0>
print(index())  # 迭代器
# <generator object index at 0x7ff534fd3a40>
res = index()
print(next(res))
# Hello World_1
# hhhh_1
print(next(res))
# Hello World_2
# hhhh_2

补充:

  1. 没有调用之前,只是一个普通的函数
  2. 加括号调用并接受结果,不执行代码,只是变成了生成器对象(迭代器)
  3. 当变成生成器对象(迭代器),可以通过 __next__取值
  4. 当函数题代码存在多个yield关键字,调用一次__next__将会执行代码,并返回yield关键字,后面的值让代码停留在yield位置,再次调用也是一样的
  5. 当没有可执行代码,再次执行则会报错 StopIteration

yield表达式作用

作用

  1. 在函数体代码中出现,可以将函数变成生成器
  2. 在执行过程中,可以将后面的值返回出去,类似于return
  3. 可以暂停住代码的运行
  4. 可以接收外界的传值

使用

def index(name):
    print(f"Hello, {name}")
    while True:
        word = yield
        print(f"Hello, {word}! --{name} ")


res = index('kevin')
res.__next__()
# Hello, kevin
res.send('world')  # send可以给yield传值,并且自动调用一次__next__方法
# Hello, world! --kevin 
res.send('hacker')  # send可以给yield传值,并且自动调用一次__next__方法
# res.send('hacker')

生成器表达式(元组推导式)

元组推导式和列表推导式的用法也完全相同,只是元组推导式是用 () 圆括号将各部分括起来,而列表推导式用的是中括号 [],另外元组推导式返回的结果是一个生成器对象。

定义

res = (表达式 for 变量名 in 循环对象)
或
res = (表达式 for 变量名 in 循环体对象 if 条件 )

使用

res = (i for i in range(10))
print(res)  # # 返回的是生成器对象
# <generator object <genexpr> at 0x7f85ab2c0a40>
print(next(res))  # 通过next取值
# 0
print(next(res))
# 1
print(next(res))
# 2
print(next(res))
# 3
print(next(res))
# 4
print(next(res))
# 5

自定义range方法

# 通过生成器模拟range方法
def my_range(start=0, end=None, step=1):
    if not end:
        end, start = start, 0
    while start < end:
        yield start
        start += step


for j in my_range(8):
    print(j)

笔试题

def add(n, i):
    return n + i

def test():
    for i in range(4):
        yield i

g = test()

for n in [1, 10]:
    g = (add(n, i) for i in g)
res = list(g)
print(res)

# A. res=[10,11,12,13]
# B. res=[11,12,13,14]
# C. res=[20,21,22,23]
# D. res=[21,22,23,24]
Last modification:March 24, 2022
如果觉得我的文章对你有用,请随意赞赏