>  기사  >  백엔드 개발  >  PHP 생성기 생성기 이해

PHP 생성기 생성기 이해

不言
不言원래의
2018-04-17 09:35:291455검색

이 기사에 소개된 내용은 PHP 생성기에 대한 이해에 관한 것입니다. 이제는 모든 사람과 공유합니다. 도움이 필요한 친구들은 이를 참조할 수 있습니다.

재인쇄 및 편집: Jifan, Fengxuezhiyu, PHP Manual
Generator


  • 해결할 수 있는 문제


공식 웹사이트에서 인용: Generator는 Iterator 인터페이스 접근 방식, 성능 오버헤드 및 복잡성이 크게 감소됩니다. 생성기를 사용하면 foreach 블록에 코드를 작성하여 메모리에 배열을 만들지 않고도 데이터 집합을 반복할 수 있습니다. 이렇게 하면 메모리 제한(강조 추가)에 도달하거나 상당한 처리 시간이 소요됩니다. 대신 일반 사용자 정의 함수처럼 생성기 함수를 작성할 수 있으며, 한 번만 반환하는 일반 함수 대신 생성기는 반복해야 하는 값을 생성하기 위해 필요한 만큼 여러 번 생성할 수 있습니다.


  • Generate는 Iterator 인터페이스를 구현합니다.

  • <?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 )
    }
    ?>
  • 키워드 수율

생성기 함수의 핵심은 수율 키워드입니다. 가장 간단한 형태에서는 일반 반환이 값을 반환하고 함수 실행을 종료한다는 점을 제외하면 return 문과 비슷해 보이지만, Yield는 생성기를 반복하고 생성기 함수의 실행을 일시 중지하는 코드에 값을 반환합니다. 생성기는 값을 반환할 수 없습니다. 그렇게 하면 컴파일 오류가 발생합니다. 그러나 return null은 유효한 구문이며 생성기 실행을 종료합니다.



         Yield는 함수에서만 사용할 수 있습니다. 그렇지 않으면 PHP 치명적인 오류가 보고됩니다. "yield" 표현식은 함수 내에서만 사용할 수 있습니다. Yield 문에 대한 코드가 실행될 때마다 실행이 일시 중지되고 Yield 문의 표현식 값이 Generator 객체에 반환됩니다. Generator 객체를 계속 반복하면 Yield 이후의 코드가 계속 실행됩니다. 모든 Yield 문이 실행되거나 return 문이 있을 때까지 return 문은 null, 즉 return;만 반환할 수 있습니다. 그렇지 않으면 컴파일 오류가 발생합니다.

  • 예제를 바탕으로 실행 과정과 사용 가능한 기능을 이해

      1 예시 1

<?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。
?>

    2 예시 2


<?php
function gen(){
    echo "1111\n";
    $ret = (yield &#39;yield1&#39;);
    var_dump($ret);
    echo "2222\n";
    $ret = (yield &#39;yield2&#39;);
    var_dump($ret);
    //return;
}
$gen = gen();
var_dump($gen->current()).PHP_EOL;
$a = $gen->send(&#39;ret1&#39;);
echo "66666\n";
var_dump($a).PHP_EOL;
echo "77777\n";
var_dump($gen->valid()).PHP_EOL;
$b = $gen->send(&#39;ret2&#39;);
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 表达式。            

相关推荐:

PHP生成器的功能与用法详解

php生成器详细介绍

위 내용은 PHP 생성기 생성기 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.