PHP中的收益率意味着什么?

我最近偶然发现了这个代码:

function xrange($min, $max) 
{
    for ($i = $min; $i <= $max; $i++) {
        yield $i;
    }
}

我从来没有见过这个yield关键字。 试图运行我得到的代码

解析错误:语法错误,第x行出现意外的T_VARIABLE

那么这个yield关键字是什么? 它甚至是有效的PHP? 如果是这样,我该如何使用它?


什么是yield

yield关键字从一个生成器函数返回数据:

生成器函数的核心是yield关键字。 在最简单的形式中,yield语句看起来很像return语句,不同之处在于,yield并不是停止函数的执行并返回,而是为循环遍历生成器的代码提供一个值,并暂停生成器函数的执行。

什么是发电机功能?

生成器函数实际上是编写迭代器的更紧凑和更高效的方式。 它允许你定义一个函数(你的xrange ),它将在循环时计算并返回值:

foreach (xrange(1, 10) as $key => $value) {
    echo "$key => $value", PHP_EOL;
}

这将创建以下输出:

0 => 1
1 => 2
…
9 => 10

您也可以通过使用来控制foreach$key

yield $someKey => $someValue;

在生成器函数中, $someKey是您想要为$key显示的任何内容, $someValue$val的值。 在问题的例子中是$i

正常功能有什么区别?

现在您可能会想知道为什么我们不是简单地使用PHP的本地range函数来实现该输出。 对,你是。 输出将是相同的。 不同的是我们如何到达那里。

当我们使用range PHP时,将执行它,在内存中创建整个数组数组,然后return整个数组returnforeach循环,然后循环它并输出值。 换句话说, foreach将在数组本身上运行。 range函数和foreach只“说”一次。 想想它就像在邮件中获取包一样。 送货员将把包裹交给你,然后离开。 然后你打开整个包裹,拿出里面的东西。

当我们使用生成器函数时,PHP将进入函数并执行它,直到它满足结束或yield关键字。 当它满足yield ,它会将当时的价值返回到外部循环。 然后它回到发电机的功能,并继续从它产生的地方。 由于你的xrange拥有一个for循环,它会执行并产生,直到达到$max 。 把它看作是像foreach和发电机打乒乓球一样。

为什么我需要这个?

显然,可以使用生成器来解决内存限制。 取决于你的环境,做一个range(1, 1000000)会致命你的脚本,而同样的发电机将工作正常。 或者如维基百科所说:

由于生成器仅在需求时计算其生成的值,因此它们对于表示一次性计算昂贵或不可能的序列很有用。 这些包括例如无限序列和实时数据流。

发电机也应该是相当快的。 但请记住,当我们谈论得很快的时候,我们通常会以非常小的数字说话。 所以,在你现在跑掉并改变你所有的代码来使用生成器之前,先做一个基准来看看它的意义。

另一个用于生成器的用例是异步协程。 yield关键字不仅返回值,还接受它们。 有关详情,请参阅下面链接的两篇优秀博客文章。

从什么时候我可以使用yield

生成器已经在PHP 5.5中引入。 尝试在该版本之前使用yield会导致各种解析错误,具体取决于关键字后面的代码。 因此,如果您从该代码中获得解析错误,请更新您的PHP。

来源和进一步阅读:

  • 官方文档
  • 最初的RFC
  • kelunik的博客:介绍发电机
  • ircmaxell的博客:什么发电机可以为你做
  • NikiC的博客:使用PHP中的协同程序进行协作式多任务处理
  • 合作PHP多任务处理
  • 发电机和阵列有什么区别?
  • 一般的发电机维基百科

  • yield关键字用于定义PHP 5.5中的“生成器”。 好的,那么什么是发电机?

    从php.net:

    生成器提供了一种简单的方法来实现简单的迭代器,而无需实现实现Iterator接口的类的开销或复杂性。

    一个生成器允许你编写使用foreach遍历一组数据的代码,而不需要在内存中建立一个数组,这可能会导致你超出内存限制,或者需要大量的处理时间来生成。 相反,您可以编写一个生成器函数,它与普通函数相同,除了不必返回一次,生成器可以根据需要产生尽可能多的次数,以便提供要迭代的值。

    从这个地方:发电机=发电机,其他功能(只是一个简单的功能)=功能。

    所以,它们在以下情况下很有用

  • 你需要做简单的事情(或简单的事情);

    生成器真的非常简单,然后实现Iterator接口。 另一方面是,发电机的功能较差。 比较它们。

  • 您需要生成大量的数据 - 节省内存;

    实际上为了节省内存,我们可以通过函数为每个循环迭代生成所需的数据,迭代后使用垃圾。 所以这里的要点是 - 清晰的代码和可能的性能。 看看什么更适合你的需求。

  • 您需要生成序列,这取决于中间值;

    这是先前思想的延伸。 与功能相比,发电机可以使事情变得更简单。 检查Fibonacci示例,并尝试在没有生成器的情况下创建序列。 在这种情况下,发生器也可以更快地工作,至少因为将中间值存储在局部变量中;

  • 你需要提高性能。

    他们可以在某些情况下工作得更快,然后执行功能(见前面的好处)


  • 简单的例子

    <?php
    echo '#start main# ';
    function a(){
        echo '{start[';
        for($i=1; $i<=9; $i++)
            yield $i;
        echo ']end} ';
    }
    foreach(a() as $v)
        echo $v.',';
    echo '#end main#';
    ?>
    

    产量

    #start main# {start[1,2,3,4,5,6,7,8,9,]end} #end main#
    
    链接地址: http://www.djcxy.com/p/58065.html

    上一篇: What does yield mean in PHP?

    下一篇: The use of htmlspecialchars() or htmlentities() in prepared statements