- 生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现Iterator接口的方式,性能开销和复杂性大大降低。
- 生成器可以yield生成多个想要的值。 任何包含yield的函数都是一个生成器函数。当一个生成器被调用的时候,它返回一个可以被遍历的对象
- 生成器是一个只能向前的迭代器,一旦开始遍历就无法后退。 同样的生成器无法遍历多遍
function data($start,$stop,$step)
{
for ($i = $start; $i >= $stop; $i += $step) {
yield $i;
}
}
//指定键名来生成值
function input_parser($input) {
foreach (explode("\n", $input) as $line) {
$fields = explode(';', $line);
$id = array_shift($fields);
yield $id => $fields;
}
}
//生成null值,yield可以在没有参数传入的情况下被调用来生成一个null值并配对一个自动的键名
function gen_three_nulls() {
foreach (range(1, 3) as $i) {
yield;
}
}
通过使用yield from关键字从另一个生成器、Traversable对象或数组生成值。然后,外部生成器将从内部生成器,对象或数组中产生所有值,直到该值不再有效为止,然后在外部生成器中继续执行
yield from不会重置key。它保留了Traversable对象或 array返回的键。因此,某些值可能与另一个yield或yield from共享一个公用键,将其插入数组后将用该键覆盖以前的值。
function inner() {
yield 1; // key 0
yield 2; // key 1
yield 3; // key 2
}
function gen() {
yield 0; // key 0
yield from inner(); // keys 0-2
yield 4; // key 1
}
生成器与Iterator对象的比较
示例的方法和类结果时相同的
<?php
function getLinesFromFile($fileName) {
if (!$fileHandle = fopen($fileName, 'r')) {
return;
}
while (false !== $line = fgets($fileHandle)) {
yield $line;
}
fclose($fileHandle);
}
// 比较下...
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);
}
}
?>