摘要:生成器允許你在代碼塊中寫代碼來迭代一組數(shù)據(jù)而不需要在內(nèi)存中創(chuàng)建一個(gè)數(shù)組那會(huì)使你的內(nèi)存達(dá)到上限,或者會(huì)占據(jù)可觀的處理時(shí)間。生成器內(nèi)部的狀態(tài)會(huì)一直在停頓和恢復(fù)之間切換,直到抵達(dá)函數(shù)定義體的末尾或遇到空的語(yǔ)句為止。
在講解生成器之前先介紹一下迭代器:
在 PHP 中,通常情況下遍歷數(shù)組使用 foreach 來遍歷。
如果我們要想讓一個(gè)對(duì)象可以遍歷呢?
PHP 為我們提供了 Iterator 接口,只要實(shí)現(xiàn)了這個(gè)接口,這個(gè)對(duì)象就可以通過 foreach 來迭代。
例子如下:
class myIterator implements Iterator { private $index = 0; private $data = ""; public function __construct($data) { $this->index = 0; $this->data = $data; } function rewind() { $this->index = 0; } function current() { return $this->data[$this->index]; } function key() { return $this->index; } function next() { ++$this->index; } function valid() { return isset($this->data[$this->index]); } } $it = new myIterator(array( "hello", "php", "iterator", )); foreach($it as $key => $value) { echo "$key : $value
"; }
我們通過foreach遍歷 $it 時(shí),PHP 會(huì)自己依次調(diào)用:
rewind() 重置到第一個(gè)元素
valid() 檢查當(dāng)前位置是否有效
current() 返回當(dāng)前元素
key() 返回當(dāng)前元素的鍵
next() 指向下一個(gè)元素
生成器是 PHP 5.5 引入的新特性,但是目前貌似很少人用到它。
下面試 PHP 官方文檔上對(duì)生成器的解釋:
生成器提供了一種更容易的方法來實(shí)現(xiàn)簡(jiǎn)單的對(duì)象迭代,相比較定義類實(shí)現(xiàn) Iterator 接口的方式,性能開銷和復(fù)雜性大大降低。
生成器允許你在 foreach 代碼塊中寫代碼來迭代一組數(shù)據(jù)而不需要在內(nèi)存中創(chuàng)建一個(gè)數(shù)組, 那會(huì)使你的內(nèi)存達(dá)到上限,或者會(huì)占據(jù)可觀的處理時(shí)間。相反,你可以寫一個(gè)生成器函數(shù),就像一個(gè)普通的自定義函數(shù)一樣, 和普通函數(shù)只返回一次不同的是, 生成器可以根據(jù)需要 yield 多次,以便生成需要迭代的值。
為了體現(xiàn)生成器的有點(diǎn),下面我們定義一個(gè)函數(shù)來進(jìn)行比較:
function func1() { foreach (range(0, 1000000) as $value){ echo $value; } } func1(); // ( ! ) Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 402653192 bytes) in xxx.php on line 5
因?yàn)閯?chuàng)建如此大的數(shù)組到內(nèi)存中進(jìn)行迭代,則 PHP 直接提示超出了單個(gè)進(jìn)程的內(nèi)存限制。
下面我們換做生成器的方式來處理:
function func1() { foreach (range(0, 1000000) as $value){ yield $value; } } var_dump(func1()); // object(Generator)[1] foreach (func1() as $value){ echo $value; }
可以看到我們調(diào)用 func1() 返回了一個(gè) Generator 對(duì)象,這個(gè)對(duì)象可以使用 foreach 迭代,每次迭代,PHP 會(huì)要求 Generator 實(shí)例計(jì)算并提供下一個(gè)要迭代的值。生成器的優(yōu)雅體現(xiàn)在每次產(chǎn)出一個(gè)值之后,生成器的內(nèi)部狀態(tài)都會(huì)停頓;向生成器請(qǐng)求下一個(gè)值時(shí),內(nèi)部狀態(tài)又會(huì)恢復(fù)。生成器內(nèi)部的狀態(tài)會(huì)一直在停頓和恢復(fù)之間切換,直到抵達(dá)函數(shù)定義體的末尾或遇到空的return語(yǔ)句為止。
參考鏈接:
https://laravelacademy.org/po...
http://php.net/manual/zh/lang...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/29416.html
摘要:它最簡(jiǎn)單的調(diào)用形式看起來像一個(gè)申明,不同之處在于普通會(huì)返回值并終止函數(shù)的執(zhí)行,而會(huì)返回一個(gè)值給循環(huán)調(diào)用此生成器的代碼并且只是暫停執(zhí)行生成器函數(shù)。 0x01 寫在前面 本文主要介紹: Generator的簡(jiǎn)單用法。 Generator的底層實(shí)現(xiàn)。 本文比較長(zhǎng),可能會(huì)耗費(fèi)你比較多的時(shí)間。如果你比較了解Generator的用法,僅想了解底層實(shí)現(xiàn),可以直接跳到底層實(shí)現(xiàn)部分。 本文分析的PH...
摘要:說到中的生成器,有人可能會(huì)想到協(xié)程,這里我們先不說如何實(shí)現(xiàn)協(xié)程,我們探究下的執(zhí)行過程。如果函數(shù)包含了關(guān)鍵字的,那么函數(shù)執(zhí)行后的返回值永遠(yuǎn)都是一個(gè)對(duì)象。如果函數(shù)內(nèi)部同事包含和該函數(shù)的返回值依然是對(duì)象,但是在生成對(duì)象時(shí),語(yǔ)句后的代碼被忽略。 說到php中的Generator(生成器),有人可能會(huì)想到協(xié)程,這里我們先不說php如何實(shí)現(xiàn)協(xié)程,我們探究下Generator的執(zhí)行過程。 Gene...
摘要:以下分別備忘版本的部分新增特性。而且,在生成器沒有輸出完全時(shí),使用會(huì)報(bào)錯(cuò)。報(bào)錯(cuò)定義常量數(shù)組多聲明數(shù)組解構(gòu)運(yùn)行時(shí)將部分指令轉(zhuǎn)為機(jī)器碼。對(duì)于計(jì)算密集型應(yīng)用有較高的性能提升。 以下分別備忘 PHP 7.0 & 7.1 版本的部分新增特性。 PHP 7.0 ?? 運(yùn)算符 $foo = null; $bar = $foo ?? 123; // 相當(dāng)于 $bar = isset($bar) ? ...
閱讀 1113·2021-11-22 14:56
閱讀 1575·2019-08-30 15:55
閱讀 3410·2019-08-30 15:45
閱讀 1681·2019-08-30 13:03
閱讀 2896·2019-08-29 18:47
閱讀 3366·2019-08-29 11:09
閱讀 2671·2019-08-26 18:36
閱讀 2640·2019-08-26 13:55