Generator
Generator implements Iterator {
/* 方法 */
public current ( ) : mixed
public key ( ) : mixed
public next ( ) : void
public rewind ( ) : void
public send ( mixed $value ) : mixed
public throw ( Exception $exception ) : void
public valid ( ) : bool
public __wakeup ( ) : void
}
Caution Generator objects cannot be instantiated via new. (Generator 对象不能通过 new 实例化.)
方法说明
Generator::current — 返回当前产生的值
Generator::key — 返回当前产生的键
Generator::next — 生成器继续执行
Generator::rewind — 重置迭代器
Generator::send — 向生成器中传入一个值
Generator::throw — 向生成器中抛入一个异常
Generator::valid — 检查迭代器是否被关闭
Generator::__wakeup — 序列化回调
建立在对Iterator的理解下,我们知道生成器允许在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使内存达到上限,或者会占据可观的处理时间。同时,写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值
function gen() {
yield 'foo';
yield 'bar';
yield 'code';
}
$g = gen();
foreach($g as $key => $value) {
var_dump($value,$key);
}
//string(3) "foo"
//int(0)
//string(3) "bar"
//int(1)
//string(4) "code"
//int(2)
等价于
$g = gen();
$g->rewind();
while ($g->valid())
{
$key = $g->key();
$value = $g->current();
var_dump($value);
$g->next();
}
//string(3) "foo"
//int(0)
//string(3) "bar"
//int(1)
//string(4) "code"
//int(2)
我们再来看一段代码用yied来生成斐波那契数来加深下理解
function fib($n)
{
$cur = 1;
$prev = 0;
for ($i = 0; $i < $n; $i++) {
yield $cur;
$temp = $cur;
$cur = $prev + $cur;
$prev = $temp;
}
}
$g = fib(9);
foreach($g as $key => $value) {
var_dump($value,$key);
}
得到
//int(1)
//int(1)
//int(2)
//int(3)
//int(5)
//int(8)
//int(13)
//int(21)
//int(34)
对于所有在generator函数中出现的yield,首先它都是语句,而跟在yield后面的任何表达式的值将作为调用generator函数的返回值,如果yield后面没有任何表达式(变量、常量都是表达式),其实yield关键字在每次执行generator 的时候会在yield 关键字时"挂起"返回
function fib($n)
{
$cur = 1;
$prev = 0;
for ($i = 0; $i < $n; $i++) {
yield $cur;
echo 'current key '.$i."\n";
$temp = $cur;
$cur = $prev + $cur;
$prev = $temp;
}
}
$g = fib(3);
echo $g->current();
echo "=======\n";
echo $g->next();
echo "=======\n";
echo $g->current();
//1 $this->current()
//=======
//current key 0 $this->next() 才执行
//=======
//1
总结
- generator 继承iterator,通过迭代返回generator对象;
- 通过yield关键字声明生成器,Generator 对象不能通过 new 实例化
- yield关键字是挂起当前位置,下次仍会往下执行到下一个yield挂起状态区别于return;
接下来参考学习下PHP 通过yiled 与generator 对象通信