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

2022-08-30 06:05:02

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

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

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

解析错误:语法错误,x 行上的意外T_VARIABLE

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


答案 1

什么?yield

关键字从生成器函数返回数据: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

您还可以通过使用$keyforeach

yield $someKey => $someValue;

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

与正常函数有什么区别?

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

当我们使用PHP时,将执行它,在内存中创建整个数字数组,并将整个数组创建到循环中,然后循环将遍历它并输出值。换句话说,will 在数组本身上运行。该功能只有一次“说话”。把它想象成在邮件中得到一个包裹。送货员会把包裹递给你并离开。然后你打开整个包装,取出里面的任何东西。rangereturnforeachforeachrangeforeach

当我们使用生成器函数时,PHP 将单步执行该函数并执行它,直到它满足 end 或关键字。当它遇到 a 时,它将向外部循环返回当时的任何值。然后它返回到生成器函数,并从它产生的地方继续。由于您持有循环,因此它将执行并产生,直到达到该循环。把它想象成和发电机打乒乓球。yieldyieldxrangefor$maxforeach

我为什么需要它?

显然,生成器可用于解决内存限制。根据您的环境,执行 a 将使您的脚本致命,而对生成器执行此操作将正常工作。或者正如维基百科所说:range(1, 1000000)

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

发电机也应该非常快。但请记住,当我们谈论快速时,我们通常谈论的人数很少。因此,在你现在运行并将所有代码更改为使用生成器之前,请进行基准测试以查看其意义所在。

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

从什么时候开始,我可以使用?yield

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

来源和延伸阅读:


答案 2

此函数使用 yield:

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()

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


推荐