The content introduced in this article is about the understanding of PHP Generator. It has a certain reference value. Now I share it with everyone. Friends in need can refer to it.
Reprinted and compiled from: Jifan, Fengxue Zhiyu, PHP manual
Generator
<?php //生成器 Generator implements Iterator { //返回当前产生的值 public mixed current ( void ) //返回当前产生的键 public mixed key ( void ) //生成器继续执行 public void next ( void ) //重置迭代器,如果迭代已经开始了,这里会抛出一个异常。 public void rewind ( void ) //向生成器中传入一个值,当前yield接收值,然后继续执行下一个yield public mixed send ( mixed $value ) //向生成器中抛入一个异常 public void throw ( Exception $exception ) //检查迭代器是否被关闭,已被关闭返回 FALSE,否则返回 TRUE public bool valid ( void ) //序列化回调 public void __wakeup ( void ) //返回generator函数的返回值,PHP version 7+ public mixed getReturn ( void ) } ?>
<?php function xrang($start, $end, $step=1){ for($i=$start; $i<=$end; $i += $step) { yield $i; //yield关键字定义了中断点 } } //foreach (xrang(1, 10000) as $num) { // echo $num."\n"; //} $rang = xrang(1,2); var_dump($rang).PHP_EOL; //输出: object(Generator)#1 (0) {} var_dump($rang instanceof Iterator).PHP_EOL; //输出: bool(true) $key = $rang->key(); var_dump("key: ".$key).PHP_EOL; //输出: string(6) "key: 0" $valid = $rang->valid(); var_dump("valid: ".$valid).PHP_EOL; //输出: string(8) "valid: 1" $current = $rang->current(); var_dump("current: ".$current).PHP_EOL; //输出: string(10) "current: 1" $rang->next(); $key = $rang->key(); var_dump("key: ".$key).PHP_EOL; //输出: string(6) "key: 1" $valid = $rang->valid(); var_dump("valid: ".$valid).PHP_EOL; //输出: string(8) "valid: 1" $current = $rang->current(); var_dump("current: ".$current).PHP_EOL; //输出: string(10) "current: 2" $rang->next(); $key = $rang->key(); var_dump("key: ".$key).PHP_EOL; //输出: string(5) "key: " $valid = $rang->valid(); var_dump("valid: ".$valid).PHP_EOL; //输出: string(7) "valid: " //$rang->rewind(); //重置,目前看到的所有文档中,rewind()仅在第一次调用Generator的时候隐式执行。生成器开始迭代后调用会抛出Fatal error。 ?>
<?php function gen(){ echo "1111\n"; $ret = (yield 'yield1'); var_dump($ret); echo "2222\n"; $ret = (yield 'yield2'); var_dump($ret); //return; } $gen = gen(); var_dump($gen->current()).PHP_EOL; $a = $gen->send('ret1'); echo "66666\n"; var_dump($a).PHP_EOL; echo "77777\n"; var_dump($gen->valid()).PHP_EOL; $b = $gen->send('ret2'); var_dump($b).PHP_EOL; var_dump($gen->valid()).PHP_EOL; //1111 //string(6) "yield1" //string(4) "ret1" //2222 //66666 //string(6) "yield2" //77777 //bool(true) //string(4) "ret2" //NULL //bool(false) ?>
2.1 执行过程为:
1.首先调用gen(),进入函数输出1111,执行到第一个yield关键字所在的位置中断(此时yield表达式的值为定义的"yield1",使用current()获取当前表达式的值即得到string(6) "yield1")
2.调用send()方法向生成器中传入值"ret1"(传入生成器的值.这个值将会被作为生成器当前所在的 yield 的返回值),此时生成器从当前所在的yield表达式开始迭代,程序继续往下执行
3.遇到var_dump输出当前表达式的值"ret1",继续执行输出2222
4.继续执行,程序来到第二个yield中断点,此时表达式的值为定义值"yield2",因为调用的是send()方法,该方法返回当前所在的yield的值(current()方法值)。(查看send方法的官方文档)
5.$a获取到send方法的返回值即"yield2",继续执行输出"66666", $a, "77777"
6.输出当前生成器是否可用
7.继续执行,向生成器中传入值"ret2",生成器开始继续迭代。此时生成器位于第二个yield表达式,该表达式接受"ret2"作为返回值赋予变量$ret,打印得到string(4) "ret2"。
8.打印之后,$b == NULL,为NULL的原因因为未彻底理解清楚(疑问之处在于此时的send()方法到底有没有返回NULL),猜测可能有如下两个原因:
8.1 一者可能是因为生成器之后没有中断点,也没有返回值(返回值不被允许,或者说仅允许返回return; return;用于终止生成器的执行),$gen->send()方法根本就没有返回任何东西,导致$b == NULL
8.2 二者可能是$gen->send('ret2')传入值后,生成器迭代完本次的yield,隐式调用了next()和current(),又因为next()下面没有yield中断点使得current()返回NULL,导致send()返回值为NULL
8.3 根据上下文,二的可能性更大
2.2 关于send()方法
send()向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。如果当这个方法被调用时,生成器不在 yield 表达式,那么在传入值之前,它会先运行到第一个 yield 表达式。
相关推荐:
The above is the detailed content of PHP generator Generator understanding. For more information, please follow other related articles on the PHP Chinese website!