首页 > 编程语言 >python yield yield from

python yield yield from

时间:2023-05-20 20:23:11浏览次数:47  
标签:迭代 python 生成器 yield next fib print

python yield

1:可迭代、迭代器、生成器
2:如何运行/激活生成器
3:生成器的执行状态
4:从生成器过渡到协程:yield

可迭代、迭代器、生成器

from collections.abc import Iterable, Iterator, Generator

isinstance(obj, Iterable)        # 可迭代对象
isinstance(obj, Iterator)        # 迭代器
isinstance(obj, Generator)       # 生成器

Iterable:可迭代对象,一般在python中想字符串,list, dict, tuple, set, deque等都是可迭代对象,一个对象只要实现了__iter__ 方法的,均可称为可迭代对象。

Iterator:迭代器,一般对象只要实现了__next__ __iter__ 方法的均可称为迭代器。

Generator:生成器,是在迭代器的基础上(可以用for循环,可以使用next()),再实现了yield

yield相当于我们函数里的return。在每次next(),或者for遍历的时候,都会yield这里将新的值返回回去,并在这里阻塞,等待下一次的调用。

可迭代象和迭代器,是将所有的值都生成存放在内存中,而生成器则是需要元素才临时生成,节省时间,节省空间。

yield关键字

yield的用法很像return,都是提供一个返回值,但是yield和return的最大区别在于,return一旦返回,则代码段执行结束,但是yield在返回值以后,会交出CUP的使用权,代码段并没有直接结束,而是在此处中断,当调用send()或者next()方法之后,yield可以从之前中断的地方继续执行。

在一个函数中,使用yield关键字,则当前的函数会变成生成器。

def fib(n):
    index = 0
    a = 0
    b = 1

    while index < n:
        yield b
        a,b = b, a+b
        index += 1
fib = fib(100)
print(fib)
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))

<generator object fib at 0x0000028AB572A270>
1
1
2
3

使用next 在生成器为空的时候会报错StopIteration,使用for 循环可以避免为空的错误

def fib(n):
    index = 0
    a = 0
    b = 1

    while index < n:
        yield b
        a,b = b, a+b
        index += 1
fib = fib(3)

print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))


1
1
2
StopIteration
def fib(n):
    index = 0
    a = 0
    b = 1

    while index < n:
        yield b
        a,b = b, a+b
        index += 1
fib = fib(3)


for i in fib:
    print(i)
    
1
1
2

使用send()方法允许我们向生成器中传值。

import time

def fib(n):
    index = 0
    a = 0
    b = 1

    while index < n:
        sleep = yield b
        print(f'等待{sleep}秒,设置n={n}')
        time.sleep(sleep)
        a,b = b, a+b
        index += 1

fib = fib(20)
print(fib.send(None))   # 效果等同于print(next(fib))
print(fib.send(1))
print(fib.send(2))
print(fib.send(3))
print(fib.send(4))

调用fib.send(None)方法,此处作用与next(fib)相同,程序返回当前b的值1, 程序中断。

调用fib.send(2)方法,程序被唤醒,将2传递给yield之前的变量sleep,程序继续运行,直到遇到yield将新的b返回,程序再次中断

如此继续下去,直到程序结束。

生成器的执行状态

GEN_CREATED 等待开始执行

GEN_RUNNING 解释器正在执行(只有在多线程应用中才能看到这个状态)

GEN_SUSPENDED 在yield表达式处暂停

GEN_CLOSED 执行结束

def simple_coro(a):
    print('-> Started: a=',a)
    b = yield a # 相当于是先返回a,暂停,直到next方法调用后,b赋值为send发送过来的数据,再执行到下一个yield暂停
    print('-> Received: b =',b)
    c = yield a+b # 先返回a+b,暂停,直到next方法调用后,c赋值为send发送过来的数据,再执行到下一个yield暂停
    print('-> Received: c=',c)

my_coro2=simple_coro(14) # 实例化一个协程对象

from inspect import getgeneratorstate # 得到状态的函数
print(getgeneratorstate(my_coro2))
next(my_coro2) 
print(getgeneratorstate(my_coro2))
my_coro2.send(28) 
my_coro2.send(99)   
print(getgeneratorstate(my_coro2))

GEN_CREATED
-> Started: a= 14
GEN_SUSPENDED
-> Received: b = 28
-> Received: c= 99
Traceback (most recent call last):
  File "d:/TzxNote/Note/lcodeNoteCards/testpy.py", line 15, in <module>
    my_coro2.send(99)
StopIteration

yield from

yield from 所在的函数被称为委托生成器,它主要为调用方子生成器提供一个双向通道

yield from 后面需要加的是可迭代对象,它可以是普通的可迭代对象,也可以是迭代器,甚至是生成器。

代替内层for循环

def generator():
    for i in range(10):
        yield i

def generator2():
	yield from range(10)

链接子生成器

def generator1():
    item = range(3)
    for i in item:
        yield i


def generator2():
    yield 'a'
    yield 'b'
    yield from generator1()
    # yield from iterable本质上等于 for item in iterable: yield item的缩写版
    yield from [11, 22, 33, 44]
    yield from range(5,10)


for i in generator2():
    print(i)
 

a
b
0
1
2
11
22
33
44
5
6
7
8
9

参考资料

https://www.cnblogs.com/cnkai/p/7514828.html

http://events.jianshu.io/p/dda2003e1aa2

标签:迭代,python,生成器,yield,next,fib,print
From: https://www.cnblogs.com/tian777/p/17417734.html

相关文章

  • Python潮流周刊#2:Rust 让 Python 再次伟大
    这里记录每周值得分享的Python及通用技术内容,部分为英文,已在小标题注明。(本期标题取自其中一则分享,不代表全部内容都是该主题,特此声明。)文章&教程1、Python修饰器的函数式编程介绍了装饰器的实现原理、带参装饰器、多装饰器、类装饰器和几个典型的示例。文章发布于2014年,代......
  • python中的装饰器原理和作用
    装饰器的作用就是用一个新函数封装旧函数(是旧函数代码不变的情况下增加功能)然后会返回一个新函数,新函数就叫做装饰器,一般为了简化装饰器会用语法糖@新函数来简化例子:这是一段代码,但功能太少,要对这个进行增强,但又不能改变代码。defhello():return"helloworld!"现在我......
  • Python数据可视化小结
    1.引言原始形式的数据对大多数人来说可能都是枯燥乏味的,但是如果掌握正确的可视化工具,给人的印象就会变得引人入胜。本文通过实际例子,让我们利用数据可视化工具来探索不一样的数据体验。闲话少说,我们直接开始吧!2.举个栗子让我们从创建一个数据集开始,假设以下数据集包含2010-2020......
  • Python自动化运维
    2-27在命令行窗口中启动的Python解释器中实现在Python自带的IDLE中实现print("Helloworld")编码规范每个import语句只导入一个模块,尽量避免一次导入多个模块不要在行尾添加分号“:”,也不要用分号将两条命令放在同一行建议每行不超过80个字符使用必要的空行可以增加代码的可读性运......
  • Python自动化
    3-20数据类型转换数据类型转换:   1.int(x):x代指对象,返回值是一个整数类型,对象->整数       x为字符串:字符串应全为整数       x为小数:只保留整数部分       x不能是负数       x为布尔类型:True=1False=0   2.float(x):x......
  • Python学习
    3-13字符串类型字符串类型:str   1.定义格式:       变量='内容'           打印一行       变量="内容"           打印一行       变量='''内容'''或者三引号           可以通过回车的方式换行,且打印出......
  • Python学习
    3-13字符串类型字符串类型:str   1.定义格式:       变量='内容'           打印一行       变量="内容"           打印一行       变量='''内容'''或者三引号           可以通过回车的方式换行,......
  • python内存管理机制
    1:引用计数机制实现垃圾回收对象引用一次,引用计数就增加1,销毁计数就减少1,当引用计数为零时,从内存中删除对象。还有一种情况,ab两对象互相引用时,del语句可以减少引用计数,但不会归零。会导致内存泄漏,解释器会定期执行一个循环检测,搜索不可访问对象的循环,并删除他们2:内存池机制为了......
  • Python编写输出斐波那契数列的前n项
    以下是一个使用Python编写的程序代码,可以计算并输出斐波那契数列的前n项(n由用户输入):n=int(input("请输入斐波那契数列的项数:"))a,b=0,1foriinrange(n):print(b,end="")a,b=b,a+b代码解释:用户输入斐波那契数列的项数n,并使用int()函数将输入的字符串......
  • 搭建python接口自动化框架
    1.最近一年接触Java接口自动化较多,倒是忘记了一些python,重拾记忆目录展示:(1)allure相关文件是集成到了插件,运行时,设置了路径之后自动创建的(2)business文件下则是业务处理脚本,可以创建app,小程序,web端的自动化脚本编写(3)common文件则是处理业务工具类,读取配置文件,excel......