1、迭代生成器
生成器的核心是一个yield关键字,一个生成器函数看起来像一个普通的函数,不同的是:普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值。生成器函数被调用时,返回的是一个可以被遍历的对象。
yield和return有点类似,不过不同的是,return会返回值并且终止代码的执行,而yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。

function gen_one_tow_three(){
for($i = 1; $i <=3; $i++){
//注意:变量$i的值在不同的yield之间是保持传递的。
yield $i;
}
}
$generator = gen_one_tow_three();
var_dump($generator);
echo "<br>";
var_dump($generator instanceof Iterator);
echo "<br>";
foreach($generator as $value){
echo $value."\n";
}

输出:
object(Generator)#1 (0) { }
bool(true)
1 2 3
调用gen_one_tow_three()的时候,里面的代码并没有真正的执行,而是返回一个生成器对象$generator = Generator Object(),$generator instanceof Interator说明Generator事项了Iterator接口,可以用foreach进行遍历,每次遍历都会隐式调用current()、next()、key()、valid()等方法。(Generator类中的方法)
2、处理大数据
下面通过实现一个xrange函数来简单说明:

function xrange($start,$end,$step = 1){
for ($i=$start; $i <=$end; $i+=$step) {
yield $i;
}
} foreach(xrange(1,1000000) as $num){
echo $num,"\n";
}

上面这个xrange()函数提供了和php的内建函数range()一样的功能,但不同的是range()函数返回的是一个包含值从1到100w的数组,而xrange()函数返回的是依次输出这些值得一个迭代器,而不会真正以数组形式返回。
这种方法的优点是显而易见的,它可以让你在处理大数据集合的时候不用一次性的加载到内存中。甚至你可以处理无限大的数据流
3、处理大文件
在PHP读取大文件的时候,经常会出现内存不足的情况,如果文件过大的话,没法一次读取玩,采用yield来实现大文件的读取。
3.1)老式读取

function readLocalFile($fileName){
$handle = fopen($fileName,'r');
$lines = [];
while(!feof($handle)){
$lines[] = fgets($handle);
}
fclose($handle);
return $lines;
}

3.2)yield读取方式

function readYieldFile($fileName){
$handle = fopen($fileName,'r');
while(!feof($handle)){
yield fgets($handle);
}
fclose($handle);
}

//为了便于测试,写一个读取内存的辅助函数

function formatBytes($bytes){
if($bytes<1024){
return $bytes . "b";
}else if($bytes <1048576){
return round($bytes / 1024,2) ."kb";
}
return round($bytes / 1048576,2) . "mb";
}
//第一种,all.zip是一个158M的压缩文件
readLocalFile('./all.zip');
echo formatBytes(memory_get_peak_usage());

报错:Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 123 bytes) in

//第二种
$lines = readYieldFile('./all.zip');
foreach($lines as $row){}
echo formatBytes(memory_get_peak_usage());

输出:141.3kb

总结:
使用老式读取,返回的是一个包含每行数据的数组,而yield方式则返回的事宜个迭代器,而不会以真正的数组返回。
这种方法的有点可以让你在处理大数据集合的时候不用一次性的加载到内存中,甚至可以处理无限大的数据流。

PHP迭代生成器---yield的更多相关文章

  1. python3使用迭代生成器yield减少内存占用

    技术背景 在python编码中for循环处理任务时,会将所有的待遍历参量加载到内存中.其实这本没有必要,因为这些参量很有可能是一次性使用的,甚至很多场景下这些参量是不需要同时存储在内存中的,这时候就会 ...

  2. 简单了解一下php的迭代生成器yield

    yield是从PHP5.5开始有的,关于yidle的说明鸟哥的博客做了详细说明,我觉得是有点复杂,在看了几篇其他的帖子还有案例,我大概知道yield的作用就是在做大量数据循环处理的时候,能节省很大一部 ...

  3. Python生成器 yield

    迭代器与list相比较,就for in句型循环拿数据而言: 用list写很简洁,但如果list数据过大,会很消耗资源. 用iteration 迭代器写,则不会消耗那么多资源.他会随用随取,用一个拿一个 ...

  4. Python入门之迭代器/生成器/yield的表达方式/面向过程编程

    本章内容 迭代器 面向过程编程 一.什么是迭代 二.什么是迭代器 三.迭代器演示和举例 四.生成器yield基础 五.生成器yield的表达式形式 六.面向过程编程 ================= ...

  5. PHP性能优化利器:生成器 yield理解

    如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生.但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明显.但是,生成 ...

  6. [PY3]——函数——生成器(yield关键字)

    函数—生成器篇 1. 认识和区分可迭代or生成器 1.1 可迭代对象 当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象 当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代 ...

  7. 6 生成器 yield 协程

    1.生成器 ----> 1 b = [x*2 for x in range(100000000000)] MemoryError: 想生成一个存放很多数据的列表,但是又不想内存占用太多 每次用一 ...

  8. day4 内置函数 迭代器&生成器 yield总结 三元运算 闭包

    内置函数: 内置函数 # abs()返回一个数字的绝对值.如果给出复数,返回值就是该复数的模. b = -100 print(b) print(abs(b)) # all() 所有为真才为真,只要有一 ...

  9. php生成器yield

    上次说了php的生成器Iterator,这次说一下yield 迭代生成器 (迭代)生成器也是一个函数,不同的是这个函数的返回值是依次返回, 而不是只返回一个单独的值.或者,换句话说,生成器使你能更方便 ...

随机推荐

  1. [Ubuntu] 移植Ubuntu16.04根文件系统到嵌入式平台

    CPU:RK3288 1.通过 ubuntu cdimage 下载 ubuntu16.04 内核,以下两种方式都可以 在 windows 系统网页中下载 http://cdimage.ubuntu.c ...

  2. Hibernate 生成策略和缓存策略

    主键生成策略 一.主键分类 1. 自然主键 主键本身就是表中的一个字段,实体中一个具体的属性,对象本身唯一的特性 比如:创建一个学生表:姓名.年龄.身份证号(自然主键) 2. 代理主键 主键本身不是表 ...

  3. fdisk交互

    fdisk交互 命令 说明 指令 a 设置可引导标记 toggle a bootable flag b 编辑bsd磁盘标签 edit bsd disklabel c 设置DOS操作系统兼容标记 tog ...

  4. 中间件 | mq消息队列解说

    消息队列 1.1 什么是消息队列 我们可以把消息队列比作是一个存放消息的容器,当我们需要使用消息的时候可以取出消息供自己使用.消息队列是分布式系统中重要的组件,使用消息队列主要是为了通过异步处理提高系 ...

  5. 遇到多个构造器参数时要考虑用构建器 builder 模式 JavaBean 线程安全

    effective java p9 JavaBeans模式阻止了把类做成不可变的可能,这需要程序员付出额外的努力来确保它的线程安全.

  6. struts2之Action与JSP相互数据传递

    package com.loaderman.crm.action; import com.loaderman.crm.entity.User; import com.loaderman.crm.ser ...

  7. linux下程序启动后后台运行实现

    关于linux下的程序运行很简单,将源码编译成二进制(假设为proram)文件后直接在命令行运行即可,root#./program如果需要后台运行,即不占用当前终端,这在嵌入式linux显得十分有必要 ...

  8. REUSE_ALV_POPUP_TO_SELECT使用技巧

    可以实现弹出一个对话框,提供选择数据的功能…… 栗子1: CALL FUNCTION 'REUSE_ALV_POPUP_TO_SELECT' TYPE-POOLS slis. DATA: selec ...

  9. mysql导入、导出 ( 带视图)

    1创建账号授权 grant all privileges on jenkinsddbes.* to 'jenkinsddbes'@'%' identified by '1iN@Da12tA&* ...

  10. 第十三章 RememberMe——《跟我学Shiro》

    转发地址:https://www.iteye.com/blog/jinnianshilongnian-2031823 目录贴:跟我学Shiro目录贴 Shiro提供了记住我(RememberMe)的功 ...