php生成器的使用 - coder5
按照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
사실적인 누드 사진을 만들기 위한 AI 기반 앱

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

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

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

인기 기사
R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
2 몇 주 전
By 尊渡假赌尊渡假赌尊渡假赌
Repo : 팀원을 부활시키는 방법
4 몇 주 전
By 尊渡假赌尊渡假赌尊渡假赌
헬로 키티 아일랜드 어드벤처 : 거대한 씨앗을 얻는 방법
3 몇 주 전
By 尊渡假赌尊渡假赌尊渡假赌
스플릿 소설을이기는 데 얼마나 걸립니까?
3 몇 주 전
By DDD
R.E.P.O. 파일 저장 위치 : 어디에 있고 그것을 보호하는 방법은 무엇입니까?
3 몇 주 전
By DDD

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

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

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

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

뜨거운 주제
Gmail 이메일의 로그인 입구는 어디에 있나요?
7313
9


자바 튜토리얼
1625
14


Cakephp 튜토리얼
1348
46


라라벨 튜토리얼
1260
25


PHP 튜토리얼
1207
29

