Rumah 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>
Salin selepas log masuk

如果需要在生成器中指定下标 可以 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>
Salin selepas log masuk

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

<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>
Salin selepas log masuk

除了通过引用来改变生成器中的数据之外,我们还可以使用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>
Salin selepas log masuk

但是上面的例子如果没有 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"));
Salin selepas log masuk

 

生成器的嵌套

<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();
Salin selepas log masuk

 

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Repo: Cara menghidupkan semula rakan sepasukan
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)