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

php生成器的使用 - coder5

May 20, 2016 am 11:40 AM

按照php的文档说明

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

<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;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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

登入後複製

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

<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方法传递数据

1

2

3

4

5

6

7

8

9

<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异常。

1

2

3

4

5

6

7

8

9

10

11

12

13

<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"));

登入後複製

 

生成器的嵌套

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

<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 Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)