PHP迭代生成器---yield
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的更多相关文章
- python3使用迭代生成器yield减少内存占用
技术背景 在python编码中for循环处理任务时,会将所有的待遍历参量加载到内存中.其实这本没有必要,因为这些参量很有可能是一次性使用的,甚至很多场景下这些参量是不需要同时存储在内存中的,这时候就会 ...
- 简单了解一下php的迭代生成器yield
yield是从PHP5.5开始有的,关于yidle的说明鸟哥的博客做了详细说明,我觉得是有点复杂,在看了几篇其他的帖子还有案例,我大概知道yield的作用就是在做大量数据循环处理的时候,能节省很大一部 ...
- Python生成器 yield
迭代器与list相比较,就for in句型循环拿数据而言: 用list写很简洁,但如果list数据过大,会很消耗资源. 用iteration 迭代器写,则不会消耗那么多资源.他会随用随取,用一个拿一个 ...
- Python入门之迭代器/生成器/yield的表达方式/面向过程编程
本章内容 迭代器 面向过程编程 一.什么是迭代 二.什么是迭代器 三.迭代器演示和举例 四.生成器yield基础 五.生成器yield的表达式形式 六.面向过程编程 ================= ...
- PHP性能优化利器:生成器 yield理解
如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生.但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明显.但是,生成 ...
- [PY3]——函数——生成器(yield关键字)
函数—生成器篇 1. 认识和区分可迭代or生成器 1.1 可迭代对象 当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象 当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代 ...
- 6 生成器 yield 协程
1.生成器 ----> 1 b = [x*2 for x in range(100000000000)] MemoryError: 想生成一个存放很多数据的列表,但是又不想内存占用太多 每次用一 ...
- day4 内置函数 迭代器&生成器 yield总结 三元运算 闭包
内置函数: 内置函数 # abs()返回一个数字的绝对值.如果给出复数,返回值就是该复数的模. b = -100 print(b) print(abs(b)) # all() 所有为真才为真,只要有一 ...
- php生成器yield
上次说了php的生成器Iterator,这次说一下yield 迭代生成器 (迭代)生成器也是一个函数,不同的是这个函数的返回值是依次返回, 而不是只返回一个单独的值.或者,换句话说,生成器使你能更方便 ...
随机推荐
- Cesium Workshop
参考资料: https://cesiumjs.org/tutorials/Cesium-Workshop/ https://github.com/geoadmin/workshop-cesium3d ...
- coercing to Unicode: need string or buffer, geoprocessing value object found
workbook.save(outxls),保存xls,出现上面的错误原因是:outxls不是错误 arcpy.AddMessage("--------"+outxls) cann ...
- lintcode刷题笔记(一)
最近开始刷lintcode,记录下自己的答案,数字即为lintcode题目号,语言为python3,坚持日拱一卒吧... (一). 回文字符窜问题(Palindrome problem) 627. L ...
- 灵活使用ssh、dsh和pssh高效管理大量计算机
http://os.iyunv.com/art/201012/240113.htm 灵活使用ssh.dsh和pssh高效管理大量计算机 http://os.iyunv.com2010-12-23 09 ...
- 算法习题---4-4骰子涂色(UVa253)
一:题目 分别对两个骰子的六个面涂色r-红 b-蓝 g-绿,通过转动骰子,看两个骰子是不是一样的涂色方法 (一)题目详解 题目规定了正方体的六个面的序号:从1-,按照这个需要提供涂色序列 (二)案例展 ...
- 【转】python selenium2 中的显示等待WebDriverWait与条件判断expected_conditions举例
#coding=utf-8 from selenium import webdriver from selenium.webdriver.common.by import By from seleni ...
- SpringCloud学习成长之路三 服务消费者(Feign)
一.Feign简介 Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单.使用Feign,只需要创建一个接口并注解. 它具有可插拔的注解特性,可使用Feign 注解和JAX-RS ...
- Apache配置优化之开启GZip传输
1.确保apache已经编译的模块里有mod_deflate模块 2.确保apache的配置文件里引入了压缩的模块 3.确保要开启Gzip压缩的虚拟主机配置里有如下配置,并重启apache服务:如果要 ...
- 使用 Sublime + PlantUML 高效地画图
转自 http://www.jianshu.com/p/e92a52770832
- Spring Boot使用JDBC方式连接MySQL
首先去spring官网下载一个名为test的Spring Boot项目模板:https://start.spring.io/ 然后在mysql中的testdb数据库中新建一张名为test_user的表 ...