PHP 生成器与迭代器对比

PHP 中的迭代器和生成器都可以用来实现同样的功能。总体来说,迭代器 ( Iterator ) 出现的比较早,在 5.1.0 版本中就出现了,也比较完备,提供了一大堆类和接口支持。比如支持数组迭代的 ArrayIterator、比如支持目录迭代的 DirectoryIterator ,还有支持使用正则表达式过滤其它迭代器的 RegexIterator

而生成器出现的比较晚,在 5.5.0 版本中才引入。并且大部分迭代器都还不支持生成器。甚至在生成器时代非常有用的 range() 函数都还不支持。

虽然生成器出现的比较晚。但它足够简单,尤其是相比较于迭代器要实现复杂的方法。生成器只要用好 yield 就可以了。

例如我们要实现一个从文件中按行读取文件。使用生成器实现一个,几乎都要实现 5 个方法

<?php 

class LineIterator implements Iterator
{
    protected $fileHandle;

    protected $line;
    protected $i;

    public function __construct($fileName) {
        if (!$this->fileHandle = fopen($fileName, 'r')) {
            throw new RuntimeException('Couldn\'t open file "' . $fileName . '"');
        }
    }

    public function rewind() {
        fseek($this->fileHandle, 0);
        $this->line = fgets($this->fileHandle);
        $this->i = 0;
    }

    public function valid() {
        return false !== $this->line;
    }

    public function current() {
        return $this->line;
    }

    public function key() {
        return $this->i;
    }

    public function next() {
        if (false !== $this->line) {
            $this->line = fgets($this->fileHandle);
            $this->i++;
        }
    }

    public function __destruct() {
        fclose($this->fileHandle);
    }
}

而实现同样的功能,对于生成器来说,只需要聊聊的几行

<?php

function getLinesFromFile($fileName) {
    if (!$fileHandle = fopen($fileName, 'r')) {
        throw new RuntimeException('Couldn\'t open file "' . $fileName . '"');
    }

    while (false !== $line = fgets($fileHandle)) {
        yield $line;
    }

    fclose($fileHandle);
}

但是,生成器并不是没有代价。生成器可以看成是一种只知道一直往前走的迭代器:生成器是只向前 ( forward-only ) 的迭代器,一旦迭代开始就无法重置。

这也意味着同一个生成器不能多次迭代:需要通过再次调用生成器函数来重建生成器。

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.