初学者理解生成器

php 2017-08-07 1,785

理解php生成器并不是一个艰巨的事情。希望你能在看完这篇文章之后完全理解他。那么,让我们开始吧。

什么是PHP生成器?

我们都知道内存管理是所有编程模块当中最难处理的。小巧,轻便和快速的应用总是人们所喜爱的。在PHP5.5当中,我们引入PHP生成器的概念。这个概念非常有用他能是我们的应用运行的更快。总的来说,这个概念就是不在内存当中创建数组。首先让我们用一个例子来解释它。创建一个generator.php在你本地,粘贴如下代码,执行代码并查看。

<?php
    function getLimit ($max = 10) {
        $array = [];

        for ($i = 1; $i < $max; $i++) {
            $array[] = $i;
        }

        return $array;
    }

    foreach (getLimit(15) as $range) {
        echo "Dataset {$range} <br>";
    }

输入结果

*Output*

我确定上面的代码并没有什么好讨论的。当然也包括输出的代码。好,现在,用下面的代码替换上面的代码。

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

我们知道PHP_INT_MAX是你当前运行php版本所能获取的最大数。之后运行你的代码在你的浏览器上。这是它会产生一个fatal/warning级别的错误。

请输入图片描述

发生了什么?

php运行内存不足?去php.ini增加memory_limit的值。是那样吗?还有其他方法吗?等一等!因为现在我们可以使用php生成器解决这个问题。让我们来看一看如何实现它。

使用PHP生成器:

定义一个和上面相同的函数并将PHP_INT_MAX传递过去。这是我们创建了一个生成器函数。

<?php

    function getLimit ($max = 10) {
        for ($i = 1; $i < $max; $i++) {
            yield $i;
        }
    }

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

Note: 再解释生成器之前,请在记住一件事生成器只能被用在函数中。
那么,来看这个getLimit,他是一个函数,这里有一个循环和一个新东西“yield”。他的用法和“return”相似。但是他和return的不同再于他不在内存当中保存完整的数据集和按需返回值。刷新你的浏览器。这时,在一段时间之后结果会输出。

为什么我们使用生成器?

通常,我们都知道我们的目标是使我们的应用速度更快但使用的内存更少。我们必须节省内存。使用生成器是内存管理的主要原因。

返回值:

生成器可以yield以前不可能出现的key-value形式。来看下面的代码。

<?php
function getLimit ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $value = $i * mt_rand();

        yield $i => $value;
    }
}

上面的代码返回key-value形式的值,并可以像数组一样使用,代码如下。

<?php

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

如何向生成器传递参数

生成器有注入参数的能力。例如,生成器可以结合搜参数来停止输出。还是使用上面的函数,

<?php

function getLimit ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $injected = yield $i;

        if ($injected === 'stop') return;
    }
}

这个参数可以被注入像

<?php

$generator = getLimit(PHP_INT_MAX);

foreach ($generator as $range) {
    if ($range === 10000) {
        $generator->send('stop');
    }

    echo "Dataset {$range} <br>";
}

不知道你有没有注意到?我们使用return和yield在同一个函数里。因为return打断了生成器的输出。

不要滥用生成器

通常,生成器被用来做内存管理,但是这并不意味这他是最终的解决方案。他们在被吴用的时候将会产生双倍的问题。但我们仍然不能否认其显著的性能。那么不妨做一个小小的重构并实现它。

原文


本文由 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

只有地板了

  1. coco
    coco

    横排二级下拉菜单

    { margin:0; padding:0;}
    ul, li { list-style:none;}
    a { text-decoration:none;}
    .nav { border:1px solid #ccc; border-right:none; overflow:hidden; float:left; margin: 100px;}
    .nav ul li { float:left;}
    .nav ul li a { width:120px; height:40px; text-align:center; line-height:40px; display:block; border-right:1px solid #ccc; background:#eee; color:#666;}

    .nav ul li a:hover{ color:#f00; }
    .nav ul li ul { position:absolute;margin-left: -1px;display: none;}
    .nav ul li ul li { float:none;}
    .nav ul li ul li a { border:1px solid #ccc; border-top:none; background:#f5f5f5;}
    .nav ul li:hover ul{ display:block; }

    栏目一 二级栏目11 二级栏目12 二级栏目13 二级栏目14 栏目二 二级栏目21 二级栏目22 二级栏目23 二级栏目24 栏目三 二级栏目31 二级栏目32 栏目四 栏目五

添加新评论