PHP 中的生成器(Generator)详解

编程之家收集整理的这篇文章主要介绍了PHP 中的生成器(Generator)详解编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

PHP 中的生成器(Generator)详解
谈到驾驶,速度并非一切。但在网络上,速度变得与众不同。你的应用程序越快,用户体验越好。这篇文章是关于 PHP 生成器的,那么我们为什么要讨论速度呢?你很快就会发现,生成器在速度和内存的管理上发挥着巨大的作用。

PHP 生成器是什么?

生成器是在 PHP 5.5 版本中添加的,它提供了一种简单的方法来遍历数据,而不需要在内存中构建数组。是不是有点疑惑?那举一个例子,展示使用生成器是一个好方式。

首先,创建一个 generator.PHP 文件,它将贯穿我们整个例子。创建文件之后,我们添加一段代码

<?PHP
function getRange ($max = 10) {
    $array = [];
    for ($i = 1; $i < $max; $i++) {
        $array[] = $i;
    }
    return $array;
}
foreach (getRange(15) as $range) {
    echo "Dataset {$range} <br>";
}

我们可以在创建 generator.PHP 文件所在目录快速启动一个内置的 PHP 服务器

PHP -S localhost:8000

如果用浏览器打开 http://localhost:8000/generator.PHP我们应该看到这样的结果:

微信截图_20200511103244.png

这段代码的自解释性并不是太好。让我们稍微改动一下代码

<?PHP
foreach (getRange(PHP_INT_MAX) as $range) {
    echo "Dataset {$range} <br>";
}

现在,上面的这段代码能够生成的最大值是 PHP_INT_MAX (也就是 PHP 能够生成的最大值). 当我们这样修改后刷新浏览器我们注意到这次有一些不一样。这段生成脚本抛出了一条 warning 信息 .

微信截图_20200511103258.png

有点遗憾的是 PHP 耗尽了内存。你能够想到的解决方法可能包括增加 PHP.ini 文件中 memory_limit 的上限。不过平心而论,这个脚本既不高效又占用内存,我们需要的是一个高效且占用内存低的脚本

使用生成

我们在上面定义相同的函数,用相同的值 PHP_INT_MAX 调用它,然后再次运行。但是这一次我们创建一个生成函数

<?PHP
function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        yIEld $i;
    }
}
foreach (getRange(PHP_INT_MAX) as $range) {
    echo "Dataset {$range} <br>";
}

解析 getRange 函数,这次,我们只循环遍历值和 yIEld 输出。 yIEld 与返回值类似,因为它也是从函数返回一个值,但唯一的区别是 yIEld 只会在需要时返回一个值,并且不会尝试将整个数据集保留在内存中。

如果您转到浏览器,您应该会看到页面显示的数据。给定适当的时间浏览器最终显示数据。

注意: 生成器只能在函数使用

为什么要使用生成

有时候,我们可能会遇到想要解析一个庞大的数据集(也可能是日志文件),也可能对一个大型数据库的结果集执行计算,等等情况。我们不想让这些数据全部加载到内存中。我们应该尽可能的保存相应的内存状态。数据不一定要很大 —— 无论数据有多小,生成器都是有效的。别忘了,我们的目的是使用更少的内存来尽可能快的处理数据。

返回键值对

有时候,我们的数据是基于 key-value 时才更有说服力。使用生成器时,我们可能会生成下面这样的键值对。

<?PHP
function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $value = $i * mt_rand();
        yIEld $i => $value;
    }
}

然后我们可以使用这个键值对,就像使用任意的数组一样。

<?PHP
foreach (getRange(PHP_INT_MAX) as $range => $value) {
    echo "Dataset {$range} has {$value} value<br>";
}

传递参数生成器中

生成器也能接收传参。这意味这生成器允许我们向其中注入参数,作为一个命令或者其他作用。例如,我们生成器发送一个值,让它停止执行或者修改输出结果。使用上面的 getRange 函数我们可以实现这一点。

<?PHP
function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $injected = yIEld $i;
        if ($injected === 'stop') return;
    }
}

要发送注入这个值,我们可以这样做。

<?PHP
$generator = getRange(PHP_INT_MAX);
foreach ($generator as $range) {
    if ($range === 10000) {
        $generator->send('stop');
    }
    echo "Dataset {$range} <br>";
}

注意: 在生成器中使用 return ,会跳出生成器。

不要滥用生成

虽然使用 PHP_INT_MAX 有点过了。但对我来说, PHP_INT_MAX 即 2147483647 也就是:

二十亿四千七百四十万四千八万三千六百四十七

生成器使内存使用更高效。但如果滥用,一样会造成内存相关的问题

总结

生成提供了难以忽视的显著性的能提升。大多数的时候,我们不需要高配置的服务器来运行代码我们只需要做一点重构,生成器是非常有用的,我们应该多多使用它们。

推荐教程:《Laravel教程》《PHP教程》《PHP7

总结

以上是编程之家为你收集整理的PHP 中的生成器(Generator)详解全部内容,希望文章能够帮你解决PHP 中的生成器(Generator)详解所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。

PHP相关文章

php中有以下五种方法来检测变量是否为空,那么这五种方法之间有什么区别呢?下面我们就来一起看看吧。1、isset功能:判断变量是否被初始化说明:它并不会判断变量是否为空,可以用来判断数组中元素是否被定义过。
字符串函数 strlen:获取字符串的长度,获取的是字符串的字节长度 字符:一个完整的符号,a,中 字节:由8位组成 一个字符最少等于一个字节:ASCII码,a,b,通常英文字符都是占用一个字节 中文在gbk或者gb2312编码里,占用两个字节 中文在utf-8里最少占用3个字节,有可能是4个字节 substr:截取字符串,以字节为单位截取 string sub...
数据的操作无外乎就是对数据的增删改查增加数据基本方式:insert into 表名 [(字段列表)] values (值列表);主键冲突:在插入数据的时候,主键值已经存在了,但是要求是必须使用该主键字段 实现目标:如果该主键不存在那么就增加记录,如果存在,就修改部分字段的值1.使用主键冲突方式语法:insert into 表名 values(值列表) on dup...
范式:Normal Format规定的一种设计方式范式特点:范式有很多,从低级到高级有六级左右,低级往高级一级比一级要求严格。关系型数据库通常设计只需要满足其中一半,满足第三范式即可。满足第三范式必须先满足第二范式,第二范式又必须先满足第一范式。第一范式:1NF数据表的设计的字段中,每个字段都不能再分,每个字段都必须是最小的不可分割的单位(原子性) 讲师代课表 要知...
在字段类型之后,用于对当前字段进行一系列的约束的内容(限制内容的情况) 字段属性:null/not null,primary key,auto_increment,unique key,comment,defaultnull表示字段的值可以为空(在进行数据插入的时候,该字段可以不给数据),not null表示不能为空,必须要给定值(不能是null)default默...
mysql中也分为三大数据类型:数值型,字符型,时间日期型 数值型数值型分为整数型和小数型(包含小数部分的数据类型)整型mysql中光整数型数据类型就有五种:tinyint,smallint,mediumint,int,bigint tinyint:迷你整型,占用1个字节保存数据,能够表示256个数值 smallint:小整型,占用2个字节保存数据,能够表示6...
校对集就是数据库数据进行比较的时候所采用的比较方式。 A =======&amp;gt; 01000001 =======&amp;gt; 65 a =======&amp;gt; 01100001 ========&amp;gt; 97校对集有三种比较方式 _bin:使用二进制进行比较(区分大小写) _ci:(case insensitive),大小写不敏感,不区分大小写(将某个字符转变成...
1.mytable1存储的数据是utf8字符集(在创建表的时候,指定了表的数据存储字符集为utf8)2.cmd控制台只能是gbk格式的数据:说明cmd下只能输入和显示gbk格式的数据3.set names gbk的功能 客户端与服务端进行不同编码的通信的原理 了解数据库的字符集 查看数据库支持哪些字符集?show character set; mysql支持39种字...
微信公众号搜索 “ 程序精选 ” ,选择关注!
微信公众号搜 "程序精选"关注