PHP中的 Iterator 與 Generator

在講解生成器以前先介紹一下迭代器:php

在 PHP 中,一般狀況下遍歷數組使用 foreach 來遍歷。html

若是咱們要想讓一個對象能夠遍歷呢?laravel

PHP 爲咱們提供了 Iterator 接口,只要實現了這個接口,這個對象就能夠經過 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<br>";
}

咱們經過foreach遍歷 $it 時,PHP 會本身依次調用:函數

rewind() 重置到第一個元素
valid() 檢查當前位置是否有效
current() 返回當前元素
key() 返回當前元素的鍵
next() 指向下一個元素post

生成器是 PHP 5.5 引入的新特性,可是目前貌似不多人用到它。
下面試 PHP 官方文檔上對生成器的解釋:
生成器提供了一種更容易的方法來實現簡單的對象迭代,相比較定義類實現 Iterator 接口的方式,性能開銷和複雜性大大下降。
生成器容許你在 foreach 代碼塊中寫代碼來迭代一組數據而不須要在內存中建立一個數組, 那會使你的內存達到上限,或者會佔據可觀的處理時間。相反,你能夠寫一個生成器函數,就像一個普通的自定義函數同樣, 和普通函數只返回一次不一樣的是, 生成器能夠根據須要 yield 屢次,以便生成須要迭代的值。性能

爲了體現生成器的有點,下面咱們定義一個函數來進行比較:this

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

由於建立如此大的數組到內存中進行迭代,則 PHP 直接提示超出了單個進程的內存限制。.net

下面咱們換作生成器的方式來處理:

function func1()
{
    foreach (range(0, 1000000) as $value){
        yield $value;
    }
}

var_dump(func1()); // object(Generator)[1]
foreach (func1() as $value){
    echo $value;
}

能夠看到咱們調用 func1() 返回了一個 Generator 對象,這個對象可使用 foreach 迭代,每次迭代,PHP 會要求 Generator 實例計算並提供下一個要迭代的值。生成器的優雅體如今每次產出一個值以後,生成器的內部狀態都會停頓;向生成器請求下一個值時,內部狀態又會恢復。生成器內部的狀態會一直在停頓和恢復之間切換,直到抵達函數定義體的末尾或遇到空的return語句爲止。

參考連接:
https://laravelacademy.org/po...
http://php.net/manual/zh/lang...

相關文章
相關標籤/搜索