什么是生成器Generators

生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。相反,你可以写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值。

一个简单的例子就是使用生成器来重新实现 range() 函数。 标准的 range() 函数需要在内存中生成一个数组包含每一个在它范围内的值,然后返回该数组, 结果就是会产生多个很大的数组。 比如,调用 range(0, 10000) 将导致内存占用超过 4 MB。

例子代码

<?php
/**
* Created by PhpStorm.
* User: chenbotome@163.com
* Date: 2018/7/30
* Time: 上午11:29
*/
$start = xdebug_memory_usage();
$num = 10000;
function rangeWithGenerators($start, $limit, $step = 1) {
if ($start < $limit) {
if ($step <= 0) {
throw new LogicException('Step must be +ve');
} for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } else { if ($step >= 0) {
throw new LogicException('Step must be -ve');
} for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
if ($argc === 1) {
$iterate = rangeWithGenerators(0, $num, 1);
foreach ($iterate as $value){
echo $value . "\n";
}
//var_dump(iterator_to_array($iterate));
}
if ($argc === 2) {
$test = range(0, $num, 1);
foreach ($test as $value) {
echo $value . "\n";
}
}
$end = xdebug_memory_usage(); echo sprintf("内存消耗量%s\n", convert($end-$start)); function convert($size){
$unit=array('b','kb','mb','gb','tb','pb');
return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
}

环境

  • PHP7.1
  • Xdebug

执行命令

  • php test.php 结果返回:内存消耗量416 b
  • php test.php range 结果返回:内存消耗量4 mb

测试结果论述

  • 通过代码的执行,比较除了PHP标准函数rang()和自定义函数rangeWithGenerators()之间的异同。实现了同样的目的,却消耗着不同的内存,生成器的优点显而易见。
  • rangeWithGenerators()使用了生成器,而生成器的关键就是使用yield关键词,yield常见的使用涉及到foreach和for两个流程控制语句。rangeWithGenerators()中for循环yield变量$i(yield可理解为生成-值,如同return可理解为返回-值)。
  • rangeWithGenerators()函数返回的便是一个生成器Generators( 使用var_dump($iterate)查看其类型 )。
  • 既然rangeWithGenerators()函数返回的是一个生成器,我们可以使用以下两种方式来使用:
  1. foreach循环该Generators,本例子中则使用该方法读取Generators。
  2. PHP标准函数iterator_to_array(),该函数将Generators转换为一个Array。

使用场景,可查阅参考资料2

参考资料:

http://php.net/manual/zh/lang...
实际生产中的使用

原文地址:https://segmentfault.com/a/1190000015879089

最新文章

  1. sql server Datetime格式转换
  2. wcf 获取客户端 IP
  3. 【缓存】EF4ProviderWrappers
  4. 常用的Python字符串常量
  5. 将四个BYTE数值转换成IEEE754标准的浮点数(两种方法:用Addr函数取字节数字的首地址,或者用Absolute关键字)
  6. CentOS下成功挂载xxxxxDVDx.iso并使用yum安装软件
  7. Linux Namespaces机制
  8. Django-CSRF跨站请求伪造防护
  9. [工作日志] 2019-04-16 入参是list
  10. 利用iftop找出是谁占用了带宽
  11. 记一次ElasticSearch重启之后shard未分配问题的解决
  12. VMware配置Linux虚拟机访问外网
  13. 【BZOJ3879】SvT(后缀自动机,虚树)
  14. 学习笔记-AngularJs(七)
  15. [转][CentOS]VI编辑器使用
  16. 8.17 纯css画一个着重号图标
  17. Android Studio 导入系统 jar包
  18. 新安装的Apache和php,测试可以解析phpinfo,但是无法打开drupal网站
  19. BZOJ4915 简单的数字题
  20. flume中Source

热门文章

  1. Wedding(2-SAT)
  2. python-----删除小于2k的文件
  3. bzoj2521
  4. js数值型遇0开始自动转换为8进制
  5. Java setAccessible方法作用
  6. 统一微信公众号、小程序、APP的用户信息
  7. 倒计时,短信发送后倒计时效果js
  8. 报错:ERROR! The server quit without updating PID file (/usr/local/var/mysql/chenyuntekiMacBook-Air.local.pid).
  9. 题解报告:hdu 3501 Calculation 2 (欧拉函数的扩展)
  10. redis在linux环境下的安装与启动