python生成器:send、yield from等用法

一边循环一遍计算的机制,称为生成器。

优点:不需要创建完整的list,从而节省内存控件。
如果一个函数中包含yield关键字,那么这个函数是一个generator。调用该函数就是创建了一个generator对象。生成器只会在响应迭代操作时才运行。

def increment(start, stop, step):
    x = start
    while x < stop:
        yield x
        x += step


a = increment(0, 2, 0.5)
print(a)

结果:

<generator object increment at 0x0000028CD9A07C10>

yield相当于return返回一个值,并且记住这个返回的位置。下次迭代时,代码从yield的下一条语句开始执行。

for n in increment(0, 2, 0.5):
    print(n)

结果:

0  # 第一次返回时没有执行 x += step
0.5
1.0
1.5

除了通过for循环可以迭代,也可通过其他可以访问可迭代对象中元素的函数,例如sum()、list()

print(sum(increment(0, 2, 0.5)))
print(list(increment(0, 2, 0.5)))

结果:

3.0
[0, 0.5, 1.0, 1.5]

生成器send()用法

def increment(start, stop, step):
    x = start
    while x < stop:
        y = yield x
        x += step
        yield y


a = increment(0, 2, 0.5)
print(next(a))  # 0
print(a.send("new value"))  # new value
print(next(a))  # 0.5
print(next(a))  # None

a = yield x send()的作用是使y赋值为send的参数,然后让生成器执行到下一个yield

next(a)启动了生成器,yield x返回0

使用send()方法,执行yield x后的代码y=,把send()内的参数new value赋值给y,遇到yield y时把y返回

第三个next()执行了y = yield x,因为不是send(),并没有给y赋值

第四个next()执行了yield y,因为上一部没有给y赋值,所以输出为None

总结:

  • 使用next()时,只会调用一次yield,下一次使用next()则执行yield之后的语句

  • 使用send()时,则会把send()的内参数赋值给yield的赋值对象,然后让生成器执行到下一个yield

  • 如果生成器内仅有一个yield,则send()的作用与next()相同

    def increment(start, stop, step):
        x = start
        while x < stop:
            x += step
            yield x
    
    a = increment(0, 2, 0.5)
    print(a.send(None))
    print(a.send("new value"))
    print(next(a))
    print(a.send("new value"))
    print(next(a))
    

    结果:

    0.5
    1.0
    1.5
    2.0
    Traceback (most recent call last):
      File "D:\personal\python_fundamental\generator_try\main.py", line 29, in <module>
        print(next(a))
    StopIteration
    

yield from用法
yield from后需要加上可迭代对象,可以把可迭代对象中的元素一个一个yield出来

# yield from
def yield_from():
    li = [1, 2, 3]
    yield from li

a = yield_from()
print(a.__next__())
print(a.__next__())
print(a.__next__())

结果:

1
2
3
# yield
def yield_from():
    li = [1, 2, 3]
    yield li

a = yield_from()
print(a.__next__())
print(a.__next__())
print(a.__next__())

结果:

[1, 2, 3]
Traceback (most recent call last):
  File "D:\personal\python_fundamental\generator_try\yield_from.py", line 8, in <module>
    print(a.__next__())
StopIteration
posted @ 2021-12-14 17:56  Ravenna  阅读(279)  评论(0编辑  收藏  举报