当前位置: 首页 > 知识库问答 >
问题:

在PHP中,收益率意味着什么?

班言
2023-03-14

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

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

我以前从未见过这个yield关键字。试图运行我得到的代码

分析错误:语法错误,第x行出现意外的T_变量

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

共有3个答案

羿博延
2023-03-14

简单的例子

<?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#

高级示例

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

输出

#start main# {start[0=>1,1=>2,2=>3,3=>4,4=>5,#end main#
冀崇凛
2023-03-14

此函数正在使用收益率:

function a($items) {
    foreach ($items as $item) {
        yield $item + 1;
    }
}

它几乎与此相同,没有:

function b($items) {
    $result = [];
    foreach ($items as $item) {
        $result[] = $item + 1;
    }
    return $result;
}

唯一的区别是a()返回一个生成器,b()只返回一个简单数组。您可以对这两种方法进行迭代。

另外,第一个阵列不分配完整的阵列,因此对内存的要求较低。

尉迟栋
2023-03-14

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

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

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

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

[…]

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

这将创建以下输出:

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

您还可以通过使用Foreach来控制$key

yield $someKey => $someValue;

在生成器函数中,$some Key是任何您希望出现在$key中的值,$some Value$val中的值。在问题的示例中,这是$i

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

当我们使用rangePHP时,将执行它,在内存中创建整个数字数组,并将整个数组返回到foreach循环,然后循环将遍历它并输出值。换句话说,foreach将对数组本身进行操作。range功能和foreach仅“通话”一次。把它想象成邮寄包裹。送货员会把包裹递给你然后离开。然后你打开整个包裹,取出里面的东西。

当我们使用generator函数时,PHP将进入该函数并执行它,直到它满足end或yield关键字。当它满足屈服时,它会将当时的值返回到外部循环。然后它返回到生成器函数,并从它产生的地方继续。由于您的xrange持有一个for循环,它将执行并产生,直到达到$max。把它想象成foreach和打乒乓球的发电机。

显然,生成器可以用来绕过内存限制。根据您的环境,执行范围(1000000)将导致脚本死亡,而对生成器执行相同的操作则可以正常工作。或者正如维基百科所说:

因为生成器只根据需要计算其生成的值,所以它们对于表示昂贵或不可能一次计算的序列非常有用。这些包括无限序列和实时数据流。

发电机也应该相当快。但是请记住,当我们谈论快速时,我们通常是在谈论非常小的数量。因此,在您现在运行并更改所有代码以使用生成器之前,请做一个基准测试,看看它在哪里有意义。

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

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

  • 官方文件

 类似资料:
  • 我正在尝试测量运行基准测试时消耗的内存。我在网上发现我可以使用< code>GC profiler来测量它。我试过了,但是我不明白答案,也看不出消耗的内存量。有人能解释这个结果吗?谢了。

  • 问题内容: 我从未见过这样的代码: 一样吗? 编辑 如果该类是继承的,它指向哪个类? 问题答案: 指向其编写所在的类。 因此,如果您的getInstance方法位于类名中,则以下行: 将做与: 编辑:评论后,还有更多信息。 如果您有两个相互扩展的类,则有两种情况: 在子类中定义 在父类中定义 第一种情况看起来像这样(在此示例中,我已经删除了所有不必要的代码-您必须将其重新添加来获得单例行为)*:

  • 问题内容: 这是什么? 这是有关警告,错误和注意事项的许多答案,这些警告,错误和注意事项在您对PHP进行编程时可能会遇到,并且不知道如何解决它们。这也是一个社区Wiki,因此邀请所有人参与添加并维护此列表。 为什么是这样? 诸如“已发送标题”或“呼叫非对象成员”之类的问题经常在堆栈溢出中弹出。这些问题的根本原因总是相同的。因此,这些问题的答案通常会重复它们,然后向OP显示在特定情况下应更改的行。这

  • 我想创建一个

  • 问题内容: 下面是代码片段。 有人可以向我解释@符号在Java中的含义吗? 问题答案: 这是一个注释。 注释是元数据的一种形式。它们提供的程序数据不属于程序本身。注释对其注释的代码的操作没有直接影响。 注释确实会影响工具和库对待程序的方式,进而会影响正在运行的程序的语义。可以从源文件,类文件中读取注释,也可以在运行时从中读取注释。

  • 问题内容: 异步在Ajax中意味着什么?以及Ajax如何知道何时在不进行服务器轮询的情况下提取数据? 问题答案: 异步意味着脚本将向服务器发送请求,并继续执行它而无需等待答复。收到答复后,立即触发浏览器事件,该事件进而允许脚本执行关联的操作。 Ajax知道何时从服务器提取数据,因为您告诉它何时进行处理。