PHP|PHP实践-生成器

PHP生成器是5.5.0引入的功能。

生成器实际上就是简单的迭代器。

与标准的PHP迭代器不同,生成器不要求类实现Iterator接口,从而减轻了类的负担。

生成器会根据需求计算产出迭代的值。而标准的PHP迭代器经常在内存中执行迭代操作,这要预先计算出数据集,性能较低。

如果使用特定的防护计算大量数据,可以使用生成器,即时计算并产出后续值,不占用内存。

生成器不能完成所有迭代器的操作。无法后退,快进,并且生成器是一次性的,无法对此迭代同一个生成器。

创建

生成器从不返回值,只是产出值。

<?php

function myGenerator() {
    yield 'v1';
    yield 'v2';
    yield 'v3';
}

调用生成器函数时,PHP会反悔一个属于Generator类的对象。这个对象是可以foreach迭代的。每次迭代,PHP要求这个实例计算并提供下一个要迭代的值。

每次产出一个值,生成器的内部状态都会停顿。向生成器请求下一个值时,内部状态才会恢复。这种停顿-恢复的状态会一直持续下去。

<?php
foreach (myGenerator() as $yieldValue) {
    echo $yieldValue , PHP_EOL;
}

使用

<?php

function makeRange($length) {
    $dataset = [];
    for ($i = 0; $i < $length; $i++) {
        $dataset[] = $i;
    }
    
    return $dataset;
}

$customRange = makeRange(1000000);
foreach ($customRange as $i) {
    echo $i, PHP_EOL;
}

上面的这个方法并没有善用内存,使用生成器只会为一个整数分配内存。

<?php
function makeRange($length) {
    for ($i = 0; $i < $length; $i++) {
        yield $i;
    }
}

foreach(makeRange(1000000) as $i) {
    echo $i, PHP_EOL;
}

再举个例子:使用生成器处理CSV文件

<?php
function getRows($file) {
    $handle = fopen($file, 'rb');
    if ($handle === false) {
        throw new Exception();
    }
    
    while (feof($handle) === false) {
        yield fgetcsv($handle);
    }
    fclose($handle);
}

foreach (getRows('data.csv') as $row) {
    print_r($row);
}

这个例子中,生成器只会为CSV文件分配一行内存,而不是读入整个文件到内存。

如果需要更多功能,例如在数据集中执行后腿,快进或查找操作,最好自己编写类,实现Iterator接口(http://php.net/manual/class.iterator.php),或者使用PHP标准库中某个原生的迭代器(http://php.net/manual/spl.iterators.php)

参考:

  1. Modern PHP

  2. http://bit.ly/ircmaxwell


ThinkingPool
Y1RReE5qazFOVFl5

Hello world!

871 声望
54 粉丝
0 条评论
推荐阅读
Java|序列化异常StreamCorruptedException的解决方法
参考:[链接] {代码...} 关键处理 byte[] str = baos.toByteArray();

niecprea阅读 3.1k

PHP转Go实践:xjson解析神器「开源工具集」
我和劲仔都是PHP转Go,身边越来越多做PHP的朋友也逐渐在用Go进行重构,重构过程中,会发现php的json解析操作(系列化与反序列化)是真的香,弱类型语言的各种隐式类型转换,很大程度的减低了程序的复杂度。

王中阳Go11阅读 2.7k评论 4

封面图
Git操作不规范,战友提刀来相见!
年终奖都没了,还要扣我绩效,门都没有,哈哈。这波骚Git操作我也是第一次用,担心闪了腰,所以不仅做了备份,也做了笔记,分享给大家。问题描述小A和我在同时开发一个功能模块,他在优化之前的代码逻辑,我在开...

王中阳Go6阅读 2.9k评论 4

封面图
图片防盗链破解 解决图片防盗链问题 反向代理
当客户端(浏览器)向服务器请求内容的时候,会提交一个header,这个header中包含了如:浏览器信息、cookie等内容,那么有一个叫referer的东东,也包含在这里面。

TANKING7阅读 11.7k评论 5

Hyperf 3.0 发布,PHP 新时代
在过去的一年半时间里,Hyperf 2.2 共发布了 35 个小版本,使 Hyperf 达到了一个前所未有的高度,这里也获得了一些不错的数据反馈。

huangzhhui4阅读 1.5k评论 1

封面图
微信公众号开发:自动回复文本/图片/图文消息/关键词回复/上传素材/自定义菜单
对接流程1、申请微信公众号测试账号URL:[链接]2、登录,配置开发者服务器URL和Token开发者服务器配置代码:config.php {代码...} URL是config.php在你服务器的URLToken是上面代码自己设置的Token搞定之后,就能完...

TANKING2阅读 10.6k

初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go3阅读 707评论 1

封面图

Hello world!

871 声望
54 粉丝
宣传栏