yield协程
1、Generator
Generator , 一种可以返回迭代器的生成器,当程序运行到yield的时候,当前程序就唤起协程记录上下文,然后主函数继续操作,当需要操作的时候,在通过迭代器的next重新调起
function xrange($start, $end, $step = 1) {
for ($i = $start; $i <= $end; $i += $step) {
yield $i;
}
}
foreach (xrange(1, 1000) as $num) {
echo $num, "\n";
}
/*
* 1
* 2
* ...
* 1000
*/
如果了解过迭代器的朋友,就可以通过上面这一段代码看出Generators的运行流程
Generators::rewind() 重置迭代器
Generators::valid() 检查迭代器是否被关闭
Generators::current() 返回当前产生的值
Generators::next() 生成器继续执行
Generators::valid()
Generators::current()
Generators::next()
...
Generators::valid() 直到返回 false 迭代结束
2、Generator应用
很多不了解的朋友看完可能会表示这有什么用呢?
举个栗子:
比如从数据库取出数亿条数据,这个时候要求用一次请求加响应返回所有值该怎么办呢?获取所有值,然后输出,这样肯定不行,因为会造成PHP内存溢出的,因为数据量太大了。如果这时候用yield就可以将数据分段获取,理论上这样是可以取出无限的数据的。
一般的获取方式 :
数据库连接.....
$sql = "select * from `user` limit 0,500000000";
$stat = $pdo->query($sql);
$data = $stat->fetchAll(); //mysql buffered query遍历巨大的查询结果导致的内存溢出
var_dump($data);
yield获取方式:
数据库连接.....
function get(){
$sql = "select * from `user` limit 0,500000000";
$stat = $pdo->query($sql);
while ($row = $stat->fetch()) {
yield $row;
}
}
foreach (get() as $row) {
var_dump($row);
}
3、Generator::send
向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。如果当这个方法被调用时,生成器不在 yield 表达式,那么在传入值之前,它会先运行到第一个 yield 表达式。As such it is not necessary to “prime” PHP generators with a Generator::next() call (like it is done in Python)
这代表了什么,这代表了我们可以使用yield进行双向通信
再举个栗子
$ben = call_user_func(function (){
$hello = (yield 'my name is ben ,what\'s your name'.PHP_EOL);
echo $hello;
});
$sayHello = $ben->current();
echo $sayHello;
$ben->send('hi ben ,my name is alex');
/*
* output
*
* my name is ben ,what's your name
* hi ben ,my name is alex
*/
这样ben跟alex他们两个就实现了一次相互问好,在这个例子中我们可以发现,yield跟以往的return不同,它不仅可以返回数据,还可以获取外部返回的数据
而且不仅仅能够send,PHP还提供了一个throw,允许我们返回一个异常给Generator
$Generatorg = call_user_func(function(){
$hello = (yield '[yield] say hello'.PHP_EOL);
echo $hello.PHP_EOL;
try{
$jump = (yield '[yield] I jump,you jump'.PHP_EOL);
}catch(Exception $e){
echo '[Exception]'.$e->getMessage().PHP_EOL;
}
});
$hello = $Generatorg->current();
echo $hello;
$jump = $Generatorg->send('[main] say hello');
echo $jump;
$Generatorg->throw(new Exception('[main] No,I can\'t jump'));
/*
* output
*
* [yield] say hello
* [main] say hello
* [yield] I jump,you jump
* [Exception][main] No,I can't jump
*/
yield协程的更多相关文章
- Unity 3D中不得不说的yield协程与消息传递
1. 协程 在Unity 3D中,我们刚开始写脚本的时候肯定会遇到类似下面这样的需求:每隔3秒发射一个烟花.怪物死亡后20秒再复活之类的.刚开始的时候喜欢把这些东西都塞到Update里面去,就像下面这 ...
- 6 生成器 yield 协程
1.生成器 ----> 1 b = [x*2 for x in range(100000000000)] MemoryError: 想生成一个存放很多数据的列表,但是又不想内存占用太多 每次用一 ...
- 20170702-变量说明,静态方法,类方法区别,断点调试,fork,yield协程,进程,动态添加属性等。。
概念: 并行:同时运行 并发:看似同时运行 json后任然中文的问题 import json d = {"名字":"初恋这件小事"} new_d1 = jso ...
- python之 yield --- “协程”
在编程中我们经常会用到列表,以前使用列表时需要声明和初始化,在数据量比较大的时候也需要把列表完整生产出来,例如要存放1000给数据,需要准备长度1000的列表,这样计算机就需要准备内存放置这个列表,在 ...
- 【Unity3D基础教程】给初学者看的Unity教程(五):详解Unity3D中的协程(Coroutine)
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 为什么需要协程 在游戏中有许多过程(Proc ...
- day-5 python协程与I/O编程深入浅出
基于python编程语言环境,重新学习了一遍操作系统IO编程基本知识,同时也学习了什么是协程,通过实际编程,了解进程+协程的优势. 一.python协程编程实现 1. 什么是协程(以下内容来自维基百 ...
- python 进程、线程与协程的区别
进程.线程与协程区别总结 - 1.进程是计算器最小资源分配单位 - 2.线程是CPU调度的最小单位 - 3.进程切换需要的资源很最大,效率很低 - 4.线程切换需要的资源一般,效率一般(当然了在不考虑 ...
- python自动化开发-[第十天]-线程、协程、socketserver
今日概要 1.线程 2.协程 3.socketserver 4.基于udp的socket(见第八节) 一.线程 1.threading模块 第一种方法:实例化 import threading imp ...
- python进阶(二) 多进程+协程
我们大多数的时候使用多线程,以及多进程,但是python中由于GIL全局解释器锁的原因,python的多线程并没有真的实现 实际上,python在执行多线程的时候,是通过GIL锁,进行上下文切换线程执 ...
随机推荐
- 收集整理的oracle常用命令大全
一.Oracle的启动和关闭 1.在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle a.启动ORACLE系统 oracle>svrmgrl ...
- js 时间格式与时间戳的相互转换示例代码
一.时间转换时间戳 function transdate(endTime){ var date=new Date(); date.setFullYear(endTime.substring(0,4)) ...
- JavaScriptDay2-简单网页表单验证
Html部分 <!-- 注册表单 1-用户名 text 2-密码 password 3-确认密码 password 4-性别 radio 5-爱好 hobby 6-籍贯 select-optio ...
- linux安装MySQL5.7记录
目录 linux安装MySQL5.7记录 1. 在根目录下创建文件夹/software和数据库数据文件/data/mysql 2. 从官网下载相应的MySQL版本 3. 解压并移动到/software ...
- Java下载execl表格
Java用POI往execl表格中写数据,并下载下来有两种方式 1.用poil的API创建表格,并设计好表格格式,然后往里面写数据 /** * execl导出 创建表格式,并写入数据 * @param ...
- Java 强制类型转换
java提高篇(十一)-----强制类型转换 在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可 ...
- LOJ1070(SummerTrainingDay05-B 矩阵快速幂)
Algebraic Problem Given the value of a+b and ab you will have to find the value of an+bn. a and bnot ...
- EasyUI动态改变输入框width
function changeEUIBoxWidth(id, width){ $('#'+id).parent().find($('span:eq(0)')).css('width',width+'p ...
- Mysql数据库 的库表简易操作
一. 库的操作 1.创建数据库 创建数据库: create database 库名 charset utf8; charset uft8 可选项 1.2 数据库命名规范: 可以由字母.数字.下划 ...
- 关于Mysql数据库的知识总结
2017年6月8日,天气阴.心情晴. 连续做梦两个晚上了,昨晚竟然梦见一个很长时间不联系的初中同学了,早上上班的路上聊了聊.女孩现在出差在贵州,风景秀美的地方.我说“你现在生活很滋润”.女孩说“那是你 ...