生成器和数组之间有什么区别?

2022-08-30 11:38:45

今天,PHP团队发布了PHP 5.5.0版本,其中包括对生成器的支持阅读文档,我注意到它完全符合数组的功能。

PHP 团队生成器示例

// Only PHP 5.5
function gen_one_to_three() {
    for ($i = 1; $i <= 3; $i++) {
        // Note that $i is preserved between yields.
        yield $i;
    }
}

$generator = gen_one_to_three();
foreach ($generator as $value) {
    echo "$value\n";
}

结果

1
2
3

但我可以使用数组做同样的事情。我仍然可以与早期版本的PHP保持兼容。

看一看

// Compatible with 4.4.9!
function gen_one_to_three() {
    $results = array();
    for ($i = 1; $i <= 3; $i++) {
        $results[] = $i;
    }

    return $results;
}

$generator = gen_one_to_three();
foreach ($generator as $value) {
    echo "$value\n";
}

那么问题来了:这个新功能存在的目的是什么?我必须在不使用新功能的情况下播放所有文档示例,将其替换为数组。

任何人都可以给出一个很好的解释,也许一个示例,这在旧版本中不一定是不可能的,但是使用生成器可以帮助开发?


答案 1

区别在于效率。例如,PHP 以外的许多语言都包含两个函数,以及 .这是生成器的一个很好的例子,以及为什么使用它们。让我们构建自己的:rangerange()xrange()

function range($start, $end) {
    $array = array();
    for ($i = $start; $i <= $end; $i++) {
        $array[] = $i;
    }
    return $array;
}

现在,这真的很简单。但是,对于大范围,它需要大量的内存。如果我们尝试使用 和 运行它,我们可能会耗尽内存!$start = 0$end = 100000000

但是,如果我们使用生成器:

function xrange($start, $end) {
    for ($i = $start; $i <= $end; $i++) {
        yield $i;
    }
}

现在我们使用常量内存,但仍然有一个“数组”(如结构),我们可以在同一空间中迭代(并与其他迭代器一起使用)。

它不会取代数组,但它确实提供了一种有效的方法来避免需要内存...

但它也在项目生成方面节省了成本。由于每个结果都是根据需要生成的,因此您可以延迟执行(获取或计算)每个元素,直到您需要它。例如,如果您需要从数据库中获取一个项目并围绕每行执行一些复杂的处理,则可以使用生成器将其延迟,直到实际需要该行:

function fetchFromDb($result) {
    while ($row = $result->fetchArray()) {
        $record = doSomeComplexProcessing($row);
        yield $record;
    }
}

因此,如果您只需要前 3 个结果,则只需处理前 3 条记录。

有关更多信息,我写了一篇关于这个确切主题的博客文章


答案 2

生成器允许对复杂语句进行惰性求值。这样可以节省内存,因为您不必一次分配所有内容。

除了两者都是可迭代的,它们几乎不相同。A 是数据结构,生成器不是。array