寫在前面
這篇文章,要和大家探討的是 PHP yield 在 生成器用法,不帶 foreach
,for
, while
循環(huán)的那種。就討論 yield
將一個(gè)函數(shù)變成為生成器的用法。
關(guān)于
yield
特性,是在開發(fā)PHP5
時(shí)被提上日程,PHP5.5
版本正式加入。
關(guān)于yield
的使用,我看到大部分文章都停留在,使用yield
如何在foreach
中穿出數(shù)據(jù),今天想給大家講講 生成器 所有語法。
相關(guān)學(xué)習(xí)推薦:PHP編程從入門到精通
官網(wǎng)講解
生成器允許你在 foreach
代碼塊中寫代碼來迭代一組數(shù)據(jù)而不需要在內(nèi)存中創(chuàng)建一個(gè)數(shù)組, 那會(huì)使你的內(nèi)存達(dá)到上限,或者會(huì)占據(jù)可觀的處理時(shí)間。相反,你可以寫一個(gè)生成器函數(shù),就像一個(gè)普通的自定義函數(shù)一樣, 和普通函數(shù)只返回一次不同的是, 生成器可以根據(jù)需要 yield
多次,以便生成需要迭代的值。
看了下官網(wǎng)對(duì)他講解:php.net 生成器語法 . 每個(gè)字都認(rèn)識(shí),但似乎還是體會(huì)到它講的內(nèi)涵。官網(wǎng)我們主要看兩部分內(nèi)容:
-
yield
的語法。 -
代碼例子。
先說語法, yield 的左邊是一個(gè)賦值語句,右邊可以是值(也可是表達(dá)式) 。而yield 會(huì)先執(zhí)行右邊的表達(dá)式,并把值$value送到生成器外面。當(dāng)生成器收到值后,會(huì)執(zhí)行yield左邊的語句,賦值給$data.
<?phpfunction func(){ $data = (yield [$express]);}
語法就這樣,估計(jì)大家還是有些懵,那就看看官網(wǎng)下面代碼例子吧,我看里面例子參差不齊。
注意yield 外面包的這一層括號(hào),如果是在php5.5,右側(cè)$express的優(yōu)先級(jí)是判斷,可能會(huì)比左側(cè)$data的賦值語句低的。所以在php5用yield,yield 右邊是可運(yùn)行表達(dá)式,左側(cè)需要接受返回并賦值,那么這個(gè)括號(hào)是有必要的。在php7不會(huì)有這個(gè)問題。
通過例子來了解它
不論是學(xué) 人類語言,計(jì)算機(jī)語言,都是模仿開始
對(duì)于一個(gè)用人類語言來描述,都不那么明晰時(shí),所以那就通過例子告訴你它能做什么,不能做什么。
相關(guān)代碼,我放到gitee了,希望你能復(fù)制到你本地運(yùn)行下,親自運(yùn)行感受下,有助于了理解接下來的內(nèi)容。
git clone gitee.com/xupaul/PHP-generator-yie…
怎樣才能產(chǎn)生 Generator
先定義一個(gè)函數(shù),在函數(shù)內(nèi) 寫個(gè) yield 關(guān)鍵詞,將這個(gè)函數(shù)調(diào)用賦值給一個(gè)變量。一個(gè)生成器就產(chǎn)生了。
代碼 /php-yield-test/yieldFunctions.php 是生成器按照不同語法組合定義了多個(gè)生成器。
測(cè)試代碼 /php-yield-test/whatIsGenerator.php,用來檢查哪些函數(shù)能構(gòu)成生成器,哪些不能。運(yùn)行結(jié)果如下
- 函數(shù)內(nèi)必須有
yield
關(guān)鍵詞,函數(shù)可以是全劇函數(shù),或者類的方法。 - 哪怕
yield
肯定不會(huì)被執(zhí)行,也會(huì)產(chǎn)生生成器。見:yield_func4 - 光禿禿 的
yield
關(guān)鍵詞就行(不向外送出,不處理外面的輸入)。見: yield_func2 - 函數(shù)內(nèi)使用 生成器 并不能讓自己也成為生成器,見:yield_func5
- eval函數(shù)中直接運(yùn)行
yield
會(huì)報(bào)錯(cuò), 見:yield_func11
是的,函數(shù)內(nèi)有沒有foreach,while,for 語句都不是關(guān)鍵,關(guān)鍵是 yield. 生成器的類型判斷用
$gen instanceof Generator
生成器的函數(shù)
Generator 對(duì)象是從 generators返回的.
Generator 對(duì)象不能通過 new 實(shí)例化.
- 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)
- Gengerator::getReturn – Get the return value of a generator
摘自 php.net generator
看著以上方法,是不想起了
Iterator
, 他們的確很像。同時(shí)注意,官網(wǎng)zh語言版本的文檔沒有索引方法getReturn
,訪問也是404。文檔以en版為準(zhǔn),ch做參考。