1.生成器函数声明
生成器函数声明就跟普通函数声明一样,区别在于:生成器函数体必须至少包含一个 yield
,可包含也可不包含 return
。
yield
与 return
的区别在于:return
会立即终止函数的执行并返回值,而 yield
会向在生成器(Generator
)类的对象上迭代的代码提供一个值,并暂停生成器函数的执行。
function 函数名(形参名) {
//函数体
}
//yield返回null
yield;
//yield返回值
yield 表达式;
//yield返回键/值对
yield 键 => 值;
//yield通过另一个生成器函数、实现了Traversable接口的类的对象、数组返回值
yield from 表达式;
2.调用生成器函数
调用生成器函数就跟调用普通函数一样。
当一个生成器函数被调用时,一个生成器(Generator
)类的对象会被返回。当迭代该对象时(例如,通过 foreach
循环),PHP 将在每次需要一个值时调用该对象的迭代方法,然后在该对象 yield
返回一个值时保存该对象的状态,以便在需要下一个值时恢复它。一旦没有更多的值要 yield
返回,那么生成器函数就停止执行。
3.示例
range()
函数需要在内存中生成一个数组以包含每一个在 range()
函数范围内的值,然后返回该数组,结果就是会产生一个很大的数组。比如,调用 range(0, 1000000)
将导致内存占用超过 100 MB。
作为一种替代方式,我们可以实现一个 xrange()
生成器函数,只需要足够的内存来创建生成器(Generator
)类的对象并在内部跟踪生成器(Generator
)类的对象的当前状态,这样只需要不到 1KB 的内存。
但是,生成器(Generator
)类的对象也有缺点:生成器(Generator
)类的对象是一个只能向前的迭代器,一旦迭代开始,就无法后退。这也意味着同一个生成器(Generator
)类的对象不能被迭代多次,只能再次调用生成器函数重新构建生成器(Generator
)类的对象。
function xrange($start, $limit, $step = 1) {
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Step must be positive');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be negative');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
echo 'Single digit odd numbers from range(): ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Single digit odd numbers from xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
//输出
Single digit odd numbers from range(): 1 3 5 7 9
Single digit odd numbers from xrange(): 1 3 5 7 9
原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/php/phplang/29218.html