婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > PHP 生成器的使用詳解

PHP 生成器的使用詳解

熱門標(biāo)簽:凱立德地鐵站地圖標(biāo)注 手機(jī)外呼系統(tǒng)什么原理 天津電銷外呼系統(tǒng)違法嗎 合肥ai電銷機(jī)器人費(fèi)用 上海400客服電話怎么申請 400電話個(gè)人能不能辦理 溫州外呼系統(tǒng)招商 滄州電銷外呼系統(tǒng)價(jià)格 銀行信貸電話機(jī)器人

什么是生成器?

聽著高大上的名字,感覺像是創(chuàng)造什么東西的一個(gè)功能,實(shí)際上,生成器是一個(gè)用于迭代的迭代器。它提供了一種更容易的方式來實(shí)現(xiàn)簡單的對象迭代,相比較定義類實(shí)現(xiàn)Iterator接口的方式,性能開銷和復(fù)雜性大大降低。

說了半天不如直接看看代碼更直觀。

function test1()
{
    for ($i = 0; $i  3; $i++) {
        yield $i + 1;
    }
    yield 1000;
    yield 1001;
}

foreach (test1() as $t) {
    echo $t, PHP_EOL;
}

// 1
// 2
// 3
// 1000
// 1001

就是這么簡單的一段代碼。首先,生成器必須在方法中并使用 yield 關(guān)鍵字;其次,每一個(gè) yield 可以看作是一次 return ;最后,外部循環(huán)時(shí),一次循環(huán)取一個(gè) yield 的返回值。在這個(gè)例子,循環(huán)三次返回了1、2、3這三個(gè)數(shù)字。然后在循環(huán)外部又寫了兩行 yield 分別輸出了1000和1001。因此,外部的 foreach 一共循環(huán)輸出了五次。

很神奇吧,明明是一個(gè)方法,為什么能夠循環(huán)它而且還是很奇怪的一種返回循環(huán)體的格式。我們直接打印這個(gè) test() 方法看看打印的是什么:

// 是一個(gè)生成器對象
var_dump(test1());

// Generator Object
// (
// )

當(dāng)使用了 yield 進(jìn)行內(nèi)容返回后,返回的是一個(gè) Generator 對象。這個(gè)對象就叫作生成器對象,它不能直接被 new 實(shí)例化,只能通過生成器函數(shù)這種方式返回。這個(gè)類包含 current() 、 key() 等方法,而且最主要的這個(gè)類實(shí)現(xiàn)了 Iterator 接口,所以,它就是一個(gè)特殊的迭代器類。

Generator implements Iterator {
    /* 方法 */
    public current ( void ) : mixed
    public key ( void ) : mixed
    public next ( void ) : void
    public rewind ( void ) : void
    public send ( mixed $value ) : mixed
    public throw ( Exception $exception ) : void
    public valid ( void ) : bool
    public __wakeup ( void ) : void
}

生成器有什么用?

搞了半天不就是個(gè)迭代器嘛?搞這么麻煩干嘛,直接用迭代器或者在方法中直接返回一個(gè)數(shù)組不就好了嗎?沒錯(cuò),正常情況下真的沒有這么麻煩,但是如果是在數(shù)據(jù)量特別大的情況下,這個(gè)生成器就能發(fā)揮它的強(qiáng)大威力了。生成器最最強(qiáng)大的部分就在于,它不需要一個(gè)數(shù)組或者任何的數(shù)據(jù)結(jié)構(gòu)來保存這一系列數(shù)據(jù)。每次迭代都是代碼執(zhí)行到 yield 時(shí)動(dòng)態(tài)返回的。因此,生成器能夠極大的節(jié)約內(nèi)存。

// 內(nèi)存占用測試
$start_time = microtime(true);
function test2($clear = false)
{
    $arr = [];
    if($clear){
        $arr = null;
        return;
    }
    for ($i = 0; $i  1000000; $i++) {
        $arr[] = $i + 1;
    }
    return $arr;
}
$array = test2();
foreach ($array as $val) {
}
$end_time = microtime(true);

echo "time: ", bcsub($end_time, $start_time, 4), PHP_EOL;
echo "memory (byte): ", memory_get_usage(true), PHP_EOL;

// time: 0.0513
// memory (byte): 35655680

$start_time = microtime(true);
function test3()
{
    for ($i = 0; $i  1000000; $i++) {
        yield $i + 1;
    }
}
$array = test3();
foreach ($array as $val) {

}
$end_time = microtime(true);

echo "time: ", bcsub($end_time, $start_time, 4), PHP_EOL;
echo "memory (byte): ", memory_get_usage(true), PHP_EOL;

// time: 0.0517
// memory (byte): 2097152

上述代碼只是簡單的進(jìn)行 1000000 個(gè)循環(huán)后獲取結(jié)果,不過也可以直觀地看出。使用生成器的版本僅僅消耗了 2M 的內(nèi)存,而未使用生成器的版本則消耗了 35M 的內(nèi)存,直接已經(jīng)10多倍的差距了,而且越大的量差距超明顯。因此,有大神將生成器說成是PHP中最被低估了的一個(gè)特性。

生成器的應(yīng)用

接下來我們來看看生成器的一些基本的應(yīng)用方式。

返回空值以及中斷

生成器當(dāng)然也可以返回空值,直接 yield; 不帶任何值就可以返回一個(gè)空值了。而在方法中直接使用 return; 也可以用來中斷生成器的繼續(xù)執(zhí)行。下面的代碼我們在 \i = 4; 的時(shí)候返回的是個(gè)空值,也就是不會(huì)輸出 5 (因?yàn)槲覀兎祷氐氖莍=4;的時(shí)候返回的是個(gè)空值,也就是不會(huì)輸出5(因?yàn)槲覀兎祷氐氖莍 + 1 )。然后在 $i == 7 的時(shí)候使用 return; 中斷生成器的繼續(xù)執(zhí)行,也就是循環(huán)最多只會(huì)輸出到 7 就結(jié)束了。

// 返回空值以及中斷
function test4()
{
    for ($i = 0; $i  10; $i++) {
        if ($i == 4) {
            yield; // 返回null值
        }
        if ($i == 7) {
            return; // 中斷生成器執(zhí)行
        }
        yield $i + 1;
    }
}

foreach (test4() as $t) {
    echo $t, PHP_EOL;
}


// 1
// 2
// 3
// 4

// 5
// 6
// 7

返回鍵值對形式

不要驚訝,生成器真的是可以返回鍵值對形式的可遍歷對象供 foreach 使用的,而且語法非常好記: yield key => value; 是不是和數(shù)組項(xiàng)的定義形式一模一樣,非常直觀好理解。

function test5()
{
    for ($i = 0; $i  10; $i++) {
        yield 'key.' . $i => $i + 1;
    }
}

foreach (test5() as $k=>$t) {
    echo $k . ':' . $t, PHP_EOL;
}

// key.0:1
// key.1:2
// key.2:3
// key.3:4
// key.4:5
// key.5:6
// key.6:7
// key.7:8
// key.8:9
// key.9:10

外部傳遞數(shù)據(jù)

我們可以通過 Generator::send 方法來向生成器中傳入一個(gè)值。傳入的這個(gè)值將會(huì)被當(dāng)做生成器當(dāng)前 yield 的返回值。然后我們根據(jù)這個(gè)值可以做一些判斷,比如根據(jù)外部條件中斷生成器的執(zhí)行。

function test6()
{
    for ($i = 0; $i  10; $i++) {
        // 正常獲取循環(huán)值,當(dāng)外部send過來值后,yield獲取到的就是外部傳來的值了
        $data = (yield $i + 1);
        if($data == 'stop'){
            return;
        }
    }
}
$t6 = test6();
foreach($t6 as $t){
    if($t == 3){
        $t6->send('stop');
    }
    echo $t, PHP_EOL;
}

// 1
// 2
// 3

上述代碼理解起來可能比較繞,但是注意記住注釋的那行話就行了(正常獲取循環(huán)值,當(dāng)外部send過來值后,yield獲取到的就是外部傳來的值了)。另外,變量獲取 yield 的值,必須要用括號括起來。

yield from 語法

yield from 語法其實(shí)就是指的從另一個(gè)可迭代對象中一個(gè)一個(gè)的獲取數(shù)據(jù)并形成生成器返回。直接看代碼

function test7()
{
    yield from [1, 2, 3, 4];
    yield from new ArrayIterator([5, 6]);
    yield from test1();
}
foreach (test7() as $t) {
    echo 'test7:', $t, PHP_EOL;
}

// test7:1
// test7:2
// test7:3
// test7:4
// test7:5
// test7:6
// test7:1
// test7:2
// test7:3
// test7:1000

在 test7() 方法中,我們使用 yield from 分別從普通數(shù)組、迭代器對象、另一個(gè)生成器中獲取數(shù)據(jù)并做為當(dāng)前生成器的內(nèi)容進(jìn)行返回。

小驚喜

生成器可以用count獲取數(shù)量嗎?

抱歉,生成器是不能用count來獲取它的數(shù)量的。

$c = count(test1()); // Warning: count(): Parameter must be an array or an object that implements Countable
// echo $c, PHP_EOL;

使用 count 來獲取生成器的數(shù)量將直接報(bào) Warning 警告。直接輸出將會(huì)一直顯示是 1 ,因?yàn)?count 的特性(強(qiáng)制轉(zhuǎn)換成數(shù)組都會(huì)顯示 1 )。

使用生產(chǎn)器來獲取斐波那契數(shù)列

// 利用生成器生成斐波那契數(shù)列
function fibonacci($item)
{
    $a = 0;
    $b = 1;
    for ($i = 0; $i  $item; $i++) {
        yield $a;
        $a = $b - $a;
        $b = $a + $b;
    }
}

$fibo = fibonacci(10);
foreach ($fibo as $value) {
    echo "$value\n";
}

這段代碼就不多解釋了,非常直觀的一段代碼了。

總結(jié)

生成器絕對是PHP中的一個(gè)隱藏的寶藏,不僅是對于內(nèi)存節(jié)約來說,而且語法其實(shí)也非常的簡潔明了。我們不需要在方法內(nèi)部再多定義一個(gè)數(shù)組去存儲返回值,直接 yield 一項(xiàng)一項(xiàng)的返回就可以了。在實(shí)際的項(xiàng)目中完全值得嘗試一把,但是嘗試完了別忘了和小伙伴們分享,大部分人可能真的沒有接觸過這個(gè)特性哦?。?/p>

測試代碼: github.com/zhangyue050…

以上就是PHP 生成器的使用詳解的詳細(xì)內(nèi)容,更多關(guān)于PHP 生成器的資料請關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • PHP Web表單生成器案例分析
  • PHP迭代器和生成器用法實(shí)例分析
  • PHP生成器(generator)和協(xié)程的實(shí)現(xiàn)方法詳解
  • PHP生成器功能與用法實(shí)例分析
  • PHP中你可能忽略的性能優(yōu)化利器:生成器
  • PHP十六進(jìn)制顏色隨機(jī)生成器功能示例
  • PHP新特性詳解之命名空間、性狀與生成器
  • php驗(yàn)證碼生成器
  • thinkPHP連接sqlite3數(shù)據(jù)庫的實(shí)現(xiàn)方法(附Thinkphp代碼生成器下載)
  • PHP5.5迭代生成器用法實(shí)例詳解

標(biāo)簽:溫州 白城 怒江 金華 七臺河 酒泉 洛陽 赤峰

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP 生成器的使用詳解》,本文關(guān)鍵詞  PHP,生,成器,的,使用,詳解,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《PHP 生成器的使用詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于PHP 生成器的使用詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    主站蜘蛛池模板: 微山县| 嘉定区| 屯门区| 哈密市| 永登县| 鄂托克前旗| 大化| 鹤峰县| 北辰区| 靖西县| 遵化市| 宁陵县| 敦化市| 荥经县| 图木舒克市| 县级市| 河西区| 石城县| 康定县| 蓝山县| 民勤县| 鄂尔多斯市| 昔阳县| 乌什县| 怀宁县| 辽源市| 靖远县| 哈巴河县| 黔南| 万盛区| 扎赉特旗| 平度市| 凯里市| 余江县| 沽源县| 舞阳县| 财经| 塘沽区| 嘉荫县| 尖扎县| 建水县|