首页 > php > php的迭代器、生成器(Generator、yield)

php的迭代器、生成器(Generator、yield)

作者:bin

一、迭代器

迭代是指反复执行一个过程,每执行一次叫做迭代一次。比如普通的遍历便是迭代

php提供了同一的迭代器接口Iterator

interface Iterator extends Traversable {

    // 返回当前的元素
    abstract public mixed current(void)
    // 返回当前元素的键
    abstract public scalar key(void)
    // 向下移动到下一个元素
    abstract public void next(void)
    // 返回到迭代器的第一个元素
    abstract public void rewind(void)
    // 检查当前位置是否有效
    abstract public boolean valid(void)
}

通过实现Iterator接口,我们可以自行决定如何遍历对象:

myIterator extends Iterator{
  public $one = 1;
  public $tow = 2;
  public $thr = 3;
}
$test = new myIterator()
foreach($test as $key => $value) {
  echo "\n";
  var_dump($key, $value);
}

当我们使用foreach遍历迭代器时,其实内部执行的顺序是:
重置->末尾?->返回当前值
->下一个->末尾?->返回当前值
->下一个->….
rewind()->valid()->current()
->next()->valid()->current()
->next->….

二、yeild和生成器

相比较迭代器,生成器提供了一种更容易的方法来实现简单的对象迭代,性能开销和复杂性都大大降低。
借用鸟叔的代码:

function xrange($start, $limit, $step = 1) {
   for ($i = $start, $j = 0; $i <= $limit; $i += $step, $j++) { // 给予键值 
    yield $j => $i;
  }
}
$xrange = xrange(1, 10, 2);
foreach ($xrange as $key => $value) {
   echo $key . ' => ' . $value . "\n";
}

生成器并不是一个普通的函数,他会在执行到yeild时暂停一次,再执行一次函数,就会走到下一个yield。

实际上生成器函数返回的是一个Generator对象,这个对象不能通过new实例化,并且实现了Iterator接口。

Generator implements Iterator {
  public mixed current(void)
  public mixed key(void)
  public void next(void)
  public void rewind(void)
  // 向生成器传入一个值
  public mixed send(mixed $value)
  public void throw(Exception $exception)
  public bool valid(void)
  // 序列化回调
  public void __wakeup(void)
}

可以看到生成器除了继承迭代器的方法,还多了一个send函数,用来向生成器传入一个参数,并且当作yield表达式多结果

function paser(){
  echo yield . '111'. "11\n";
  echo yield "2222\n";
}

$one = paser();

$one->send('1nihao');
$one->send('2nihao');

输出结果
第一行因为是字符串拼接,所以将yield替换,然后拼接输出
第二行因为是定义,所以”2222\n”被替换为2nihao了

1nihao11111
2nihao

您必须 [ 登录 ] 才能发表留言!