摘要:說到中的生成器,有人可能會(huì)想到協(xié)程,這里我們先不說如何實(shí)現(xiàn)協(xié)程,我們探究下的執(zhí)行過程。如果函數(shù)包含了關(guān)鍵字的,那么函數(shù)執(zhí)行后的返回值永遠(yuǎn)都是一個(gè)對(duì)象。如果函數(shù)內(nèi)部同事包含和該函數(shù)的返回值依然是對(duì)象,但是在生成對(duì)象時(shí),語句后的代碼被忽略。
說到php中的Generator(生成器),有人可能會(huì)想到協(xié)程,這里我們先不說php如何實(shí)現(xiàn)協(xié)程,我們探究下Generator的執(zhí)行過程。
Generator是通過yield實(shí)現(xiàn),yield 關(guān)鍵字是php5.5版本推出的一個(gè)特性。
首先,看下面的代碼:
function gen(){ while(true){ yield "gen "; } } $gen = gen(); echo "Generator";
如果沒有了解過yield的話,你會(huì)認(rèn)為上面代碼執(zhí)行的結(jié)果是:死循環(huán)。但實(shí)際上,它會(huì)echo出Generator。
到這里,也許你會(huì)覺得奇怪,yield怎么可以結(jié)束循環(huán)?下面就為大家說明一下:
Generator提供的方法:
Generator::current — 返回當(dāng)前產(chǎn)生的值 Generator::key — 返回當(dāng)前產(chǎn)生的鍵 Generator::next — 生成器繼續(xù)執(zhí)行 Generator::rewind — 重置迭代器 Generator::send — 向生成器中傳入一個(gè)值 Generator::throw — 向生成器中拋入一個(gè)異常 Generator::valid — 檢查迭代器是否被關(guān)閉 Generator::__wakeup — 序列化回調(diào) 生成器提供了一種更容易的方法來實(shí)現(xiàn)簡單的對(duì)象迭代(迭代器),相比較定義類實(shí)現(xiàn) Iterator 接口的方式,性能開銷和復(fù)雜性大大降低。
列子:
function gen(){ for($i=0;$i<5;$i++) { echo (yield $i).$i."
"; } } $gen = gen(); foreach($gen as $k=>$v){ echo "{$k}---{$v}"."
"; }
結(jié)果是:
從上面的結(jié)果,我們可以分析出以下幾點(diǎn):
1當(dāng)Generator對(duì)象被foreach的時(shí)候,內(nèi)部的valid,current,key方法會(huì)依次被調(diào)用,其返回值是foreach語句的value和key。
2循環(huán)的終止條件則根據(jù)valid方法的返回而定。如果返回的是true則繼續(xù)循環(huán),如果是false則終止整個(gè)循環(huán),結(jié)束遍歷。
3一次循環(huán)體結(jié)束之后,將調(diào)用next進(jìn)行下一次的循環(huán)直到valid返回false。而rewind方法則是在整個(gè)循環(huán)開始前被調(diào)用(也就是生成Generator對(duì)象時(shí)),這樣保證了我們多次遍歷得到的結(jié)果都是一致的。
下面我們來證明一下這個(gè)流程:
$gen = gen();
echo $gen->key();//結(jié)果是0,生成Generator對(duì)象時(shí),rewind已經(jīng)執(zhí)行。
echo $gen->key()."----".$gen->current();// 0----0
var_dump($gen->next());//var_dump值是null,但是還會(huì)echo出多一個(gè)0;這個(gè)0是怎樣來的呢?原因是:next()執(zhí)行后,第1個(gè)yield到第二個(gè)yieldz之間的的語法被執(zhí)行,即是:echo (yield $i).$i."
";由于next()是沒有返回值,即(yield $i)這個(gè)表達(dá)式?jīng)]有值,而$i的值是0;
echo $gen->key()."----".$gen->current();// 1----1 目前是第2個(gè)yield
上面這個(gè)例子可以證明,Generator內(nèi)部的流程,特別注意next()的理解。
最后,我們說一下,send():
官方解析:向生成器中傳入一個(gè)值,并且當(dāng)做 yield 表達(dá)式的結(jié)果,然后繼續(xù)執(zhí)行生成器。如果當(dāng)這個(gè)方法被調(diào)用時(shí),生成器不在 yield 表達(dá)式,那么在傳入值之前,它會(huì)先運(yùn)行到第一個(gè) yield 表達(dá)式。
翻譯下的結(jié)論是:
send()方法主要用于發(fā)送數(shù)據(jù)給當(dāng)前yield,即yield表達(dá)式被當(dāng)作一個(gè)值被替換,且繼續(xù)執(zhí)行下一個(gè)yield,即next()
證明例子:
$gen = gen();
$gen->send(666);//6660
6660結(jié)果分析:首先把666代替當(dāng)前yield表達(dá)式的值,然后執(zhí)行next(),即運(yùn)行echo (yield $i).$i."
",當(dāng)前yield是666,所以最終結(jié)果是:6660。注意與next()的區(qū)別!!!
總結(jié):
1.yield只能用于函數(shù)內(nèi)部,在非函數(shù)內(nèi)部運(yùn)用會(huì)拋出錯(cuò)誤。
2.如果函數(shù)包含了yield關(guān)鍵字的,那么函數(shù)執(zhí)行后的返回值永遠(yuǎn)都是一個(gè)Generator對(duì)象。
3.如果函數(shù)內(nèi)部同事包含yield和return 該函數(shù)的返回值依然是Generator對(duì)象,但是在生成Generator對(duì)象時(shí),return語句后的代碼被忽略。
4.Generator類實(shí)現(xiàn)了Iterator接口。
5.可以通過返回的Generator對(duì)象內(nèi)部的方法,獲取到函數(shù)內(nèi)部yield后面表達(dá)式的值。
6.可以通過Generator的send方法給yield 關(guān)鍵字賦一個(gè)值。
7.一旦返回的Generator對(duì)象被遍歷完成,便不能調(diào)用他的rewind方法來重置。
8.Generator對(duì)象不能被clone關(guān)鍵字克隆 。
實(shí)際應(yīng)用:
1.協(xié)程
2.Genenrator返回的是迭代器,在處理大數(shù)據(jù)的時(shí)候不用一次性的加載到內(nèi)存中,可看http://php.net/manual/zh/lang...。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/28265.html
摘要:它最簡單的調(diào)用形式看起來像一個(gè)申明,不同之處在于普通會(huì)返回值并終止函數(shù)的執(zhí)行,而會(huì)返回一個(gè)值給循環(huán)調(diào)用此生成器的代碼并且只是暫停執(zhí)行生成器函數(shù)。 0x01 寫在前面 本文主要介紹: Generator的簡單用法。 Generator的底層實(shí)現(xiàn)。 本文比較長,可能會(huì)耗費(fèi)你比較多的時(shí)間。如果你比較了解Generator的用法,僅想了解底層實(shí)現(xiàn),可以直接跳到底層實(shí)現(xiàn)部分。 本文分析的PH...
摘要:的方法在中,提供了方法來拋出異常。總結(jié)關(guān)于生成器的異常處理,這里來進(jìn)行一下總結(jié)。最近在研究使用實(shí)現(xiàn)半?yún)f(xié)程,而這個(gè)過程中,對(duì)異常的處理,是非常重要的。但是的運(yùn)行方式?jīng)Q定了異常處理比較難以理解。 本文是我在研究 PHP 異步編程時(shí)的總結(jié)。對(duì)于相當(dāng)多的 PHPer 來說,可能都不知道 Generator,或者對(duì) Generaotr 的流程不是很熟悉。因?yàn)?Generator 使得程序不再是順...
摘要:本文先回顧生成器,然后過渡到協(xié)程編程。其作用主要體現(xiàn)在三個(gè)方面數(shù)據(jù)生成生產(chǎn)者,通過返回?cái)?shù)據(jù)數(shù)據(jù)消費(fèi)消費(fèi)者,消費(fèi)傳來的數(shù)據(jù)實(shí)現(xiàn)協(xié)程。解決回調(diào)地獄的方式主要有兩種和協(xié)程。重點(diǎn)應(yīng)當(dāng)關(guān)注控制權(quán)轉(zhuǎn)讓的時(shí)機(jī),以及協(xié)程的運(yùn)作方式。 轉(zhuǎn)載請(qǐng)注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎(chǔ) web請(qǐng)求 cookie web響應(yīng) sess...
摘要:在中,我們都知道,有一個(gè)函數(shù)叫做,用來生成一個(gè)等差數(shù)列的數(shù)組,然后我們可以用這個(gè)數(shù)組進(jìn)行的迭代。這一段代碼就會(huì)輸出首項(xiàng)為,末項(xiàng)為,公差為的等差數(shù)列。它的執(zhí)行順序是這樣的。 何為 Generator 從 PHP 5.5 開始,PHP 加入了一個(gè)新的特性,那就是 Generator,中文譯為生成器。生成器可以簡單地用來實(shí)現(xiàn)對(duì)象的迭代,讓我們先從官方的一個(gè)小例子說起。 xrange 在 PH...
閱讀 3156·2021-11-22 09:34
閱讀 2796·2021-09-22 15:28
閱讀 816·2021-09-10 10:51
閱讀 1853·2019-08-30 14:22
閱讀 2273·2019-08-30 14:17
閱讀 2734·2019-08-30 11:01
閱讀 2295·2019-08-29 17:19
閱讀 3653·2019-08-29 13:17