我最近偶然发现了这个代码:
function xrange($min, $max)
{
for ($i = $min; $i <= $max; $i++) {
yield $i;
}
}
我以前从未见过这个yield
关键字。试图运行我得到的代码
分析错误:语法错误,第x行出现意外的T_变量
那么这个产量
关键字是什么?它甚至是有效的PHP吗?如果是,我该如何使用它?
简单的例子
<?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#
此函数正在使用收益率:
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()
只返回一个简单数组。您可以对这两种方法进行迭代。
另外,第一个阵列不分配完整的阵列,因此对内存的要求较低。
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
函数来实现该输出。你是对的。输出将是相同的。区别在于我们是如何到达那里的。
当我们使用range
PHP时,将执行它,在内存中创建整个数字数组,并将整个数组返回到
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知道何时从服务器提取数据,因为您告诉它何时进行处理。