php教程 php手册 php生成器的使用 - coder5

php生成器的使用 - coder5

May 20, 2016 am 11:40 AM

按照php的文档说明

一个生成器函数看起来像一个普通的函数,不同的是普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值。
当一个生成器被调用的时候,它返回一个可以被遍历的对象.当你遍历这个对象的时候(例如通过一个foreach循环),PHP 将会在每次需要值的时候调用生成器函数,并在产生一个值之后保存生成器的状态,这样它就可以在需要产生下一个值的时候恢复调用状态。
一旦不再需要产生更多的值,生成器函数可以简单退出,而调用生成器的代码还可以继续执行,就像一个数组已经被遍历完了。

一个生成器不可以返回值: 这样做会产生一个编译错误。然而return空是一个有效的语法并且它将会终止生成器继续执行。

<span style="color: #008000;">/*</span><span style="color: #008000;">*
 * 安原来的写法,我需要一个方法来整理数据。nums()会返回一个数组或者其他可以迭代的数据
 * 然后再遍历这个数组
 </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">function</span><span style="color: #000000;"> nums() {
    </span><span style="color: #800080;">$array</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">();
    </span><span style="color: #0000ff;">for</span> (<span style="color: #800080;">$i</span> = 0; <span style="color: #800080;">$i</span> $i<span style="color: #000000;">) {
        </span><span style="color: #800080;">$array</span>[]= <span style="color: #800080;">$i</span><span style="color: #000000;">;
    }
    </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$array</span><span style="color: #000000;">;
}

</span><span style="color: #0000ff;">foreach</span> (nums() <span style="color: #0000ff;">as</span> <span style="color: #800080;">$v</span><span style="color: #000000;">){
    </span><span style="color: #008080;">var_dump</span>(<span style="color: #800080;">$v</span><span style="color: #000000;">);
};


</span><span style="color: #008000;">/*</span><span style="color: #008000;">*
 * 但是用了yield之后,我不再需要创建一个变量,来存储这个数据。
 * 而是在内部会为生成的值配对连续的整型索引,就像一个非关联的数组。 
 * 这样会省掉很大的内存开销
 </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">function</span><span style="color: #000000;"> nums2() {
    </span><span style="color: #0000ff;">for</span> (<span style="color: #800080;">$i</span> = 0; <span style="color: #800080;">$i</span> $i<span style="color: #000000;">) {
        yield </span><span style="color: #800080;">$i</span><span style="color: #000000;">;
    }
}

</span><span style="color: #0000ff;">foreach</span> (nums2() <span style="color: #0000ff;">as</span> <span style="color: #800080;">$v</span><span style="color: #000000;">){
    </span><span style="color: #008080;">var_dump</span>(<span style="color: #800080;">$v</span><span style="color: #000000;">);
};</span>
로그인 후 복사

如果需要在生成器中指定下标 可以 yield $id => $fields;

<span style="color: #800080;">$handler</span>=<span style="color: #0000ff;">function</span><span style="color: #000000;">() {
        </span><span style="color: #800080;">$start</span> = <span style="color: #008080;">microtime</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">);

        yield;

        </span><span style="color: #800080;">$use_time</span> = (<span style="color: #008080;">microtime</span>(<span style="color: #0000ff;">true</span>) - <span style="color: #800080;">$start</span>) * 1000<span style="color: #000000;">;
        </span><span style="color: #0000ff;">echo</span> "the time is ".(int)<span style="color: #800080;">$use_time</span>."ms\n"<span style="color: #000000;">;
        
        yield;
        </span><span style="color: #800080;">$use_time</span> = (<span style="color: #008080;">microtime</span>(<span style="color: #0000ff;">true</span>) - <span style="color: #800080;">$start</span>) * 1000<span style="color: #000000;">;
        </span><span style="color: #0000ff;">echo</span> "the time2 is ".(int)<span style="color: #800080;">$use_time</span>."ms\n"<span style="color: #000000;">;
};

</span><span style="color: #008000;">//</span><span style="color: #008000;">根据文档的说明 当一个生成器被调用的时候,它返回一个可以被遍历的对象.当你遍历这个对象的时候
//PHP 将会在每次需要值的时候调用生成器函数,
//也就是说此时并没有真的调用$handler中定义的函数。而是返回了一个生成器</span>
<span style="color: #800080;">$generator</span> = <span style="color: #008080;">call_user_func_array</span>(<span style="color: #800080;">$handler</span>,<span style="color: #0000ff;">array</span><span style="color: #000000;">());

</span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$generator</span> && <span style="color: #800080;">$generator</span><span style="color: #000000;"> instanceof \Generator) {

    </span><span style="color: #008000;">//</span><span style="color: #008000;">当对生成器进行迭代的时候,才会真正的调用该$handler中定义的函数</span>
    <span style="color: #0000ff;">if</span> (<span style="color: #800080;">$generator</span>-><span style="color: #008080;">current</span>() === <span style="color: #0000ff;">false</span><span style="color: #000000;">) {
        </span><span style="color: #008000;">/*</span><span style="color: #008000;">**do some thing*</span><span style="color: #008000;">*/</span><span style="color: #000000;">
    }
}</span>
로그인 후 복사

生成器也可以通过引用来使用

<span style="color: #008000;">/*</span><span style="color: #008000;">*
 * 使用引用来生成值
 </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">function</span> &<span style="color: #000000;">gen_reference() {
    </span><span style="color: #800080;">$value</span> = 3<span style="color: #000000;">;

    </span><span style="color: #0000ff;">while</span> (<span style="color: #800080;">$value</span> > 0<span style="color: #000000;">) {
        yield </span><span style="color: #800080;">$value</span><span style="color: #000000;">;
    }
}
</span><span style="color: #008000;">/*</span><span style="color: #008000;"> 
 * 我们可以在循环中修改$number的值,而生成器是使用的引用值来生成,所以gen_reference()内部的$value值也会跟着变化。
 </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">foreach</span> (gen_reference() <span style="color: #0000ff;">as</span> &<span style="color: #800080;">$number</span><span style="color: #000000;">) {
    </span><span style="color: #0000ff;">echo</span> (--<span style="color: #800080;">$number</span>).'... '<span style="color: #000000;">;
}</span>
로그인 후 복사

除了通过引用来改变生成器中的数据之外,我们还可以使用send方法传递数据

<span style="color: #0000ff;">function<span style="color: #000000;"> printer() {
    <span style="color: #0000ff;">while (<span style="color: #0000ff;">true<span style="color: #000000;">) {
        <span style="color: #800080;">$string =<span style="color: #000000;"> yield;
        <span style="color: #0000ff;">echo <span style="color: #800080;">$string<span style="color: #000000;">;
    }
}

<span style="color: #800080;">$printer =<span style="color: #000000;"> printer();
<span style="color: #800080;">$printer->send('Hello world!');</span></span></span></span></span></span></span></span></span></span></span></span></span>
로그인 후 복사

但是上面的例子如果没有 while(true),那么无论后面send多少次,该生成器只会执行一次。如此说来,似乎可以用这个来控制本函数调用的最多次数?

除了向里面传递数据之外,还可以throw异常。

<span style="color: #0000ff;">function</span><span style="color: #000000;"> application() {
    </span><span style="color: #0000ff;">while</span> (<span style="color: #0000ff;">true</span><span style="color: #000000;">){
        </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
            </span><span style="color: #000000;"> yield;
</span><span style="color: #000000;">
        }</span><span style="color: #0000ff;">catch</span> (<span style="color: #0000ff;">Exception</span> <span style="color: #800080;">$e</span><span style="color: #000000;">){
            </span><span style="color: #0000ff;">echo</span> <span style="color: #800080;">$e</span><span style="color: #000000;">;
        }
    }
}

</span><span style="color: #800080;">$printer</span> =<span style="color: #000000;"> <span style="color: #000000;">application</span>();
</span><span style="color: #800080;">$printer</span>-><span style="color: #0000ff;">throw</span>(<span style="color: #0000ff;">new</span>  <span style="color: #0000ff;">Exception</span>("test"));
로그인 후 복사

 

生成器的嵌套

<span style="color: #008000;">/*</span><span style="color: #008000;">*
 * 在php7中 可以通过yield from 进行嵌套
 </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">function</span><span style="color: #000000;"> count_to_ten() {
    yield </span>1<span style="color: #000000;">;
    yield </span>2<span style="color: #000000;">;
    yield from [</span>3, 4<span style="color: #000000;">];
    yield from </span><span style="color: #0000ff;">new</span> ArrayIterator([5, 6<span style="color: #000000;">]);
    yield from seven_eight();
    yield </span>9<span style="color: #000000;">;
    yield </span>10<span style="color: #000000;">;
}

</span><span style="color: #0000ff;">function</span><span style="color: #000000;"> seven_eight() {
    yield </span>7<span style="color: #000000;">;
    yield from eight();
}

</span><span style="color: #0000ff;">function</span><span style="color: #000000;"> eight() {
    yield </span>8<span style="color: #000000;">;
}

</span><span style="color: #800080;">$gen</span> =<span style="color: #000000;"> count_to_ten();
</span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$gen</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$num</span><span style="color: #000000;">) {
    </span><span style="color: #0000ff;">echo</span> "<span style="color: #800080;">$num</span> "<span style="color: #000000;">;
}
</span><span style="color: #0000ff;">echo</span> "the return value is ".<span style="color: #800080;">$gen</span>->getReturn();
로그인 후 복사

 

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

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)