PHP Generator

概念

PHP Generator,是迭代器接口的实现。
只要是包含yield关键字的函数,那么这个函数的返回值就是一个Generator对象。
只有在迭代这个Generator对象的时候,其代码才会执行,其中的yield会中断代码执行,当再次迭代到的时候,会继续执行。
由于Generator是迭代器接口的实现,所以迭代器接口的方法,可以直接使用。
这里附上迭代器接口文档:https://www.php.net/manual/zh/class.iterator.php

迭代器Iterator

需要先了解一下迭代器,实现了迭代器接口的类就叫迭代器。

一个迭代器的例子:

class Xrange implements Iterator
{
    protected $start;
    protected $limit;
    protected $step;
    protected $i;

    public function __construct($start, $limit, $step = 0)
    {
        $this->start = $start;
        $this->limit = $limit;
        $this->step  = $step;
    }

    public function rewind()
    {
        $this->i = $this->start;
    }

    public function next()
    {
        $this->i += $this->step;
    }

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

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

    public function valid()
    {
        return $this->i <= $this->limit;
    }
}

使用这个迭代器:

foreach (new Xrange(0, 10, 1) as $key => $value) {
    printf("%d %d\n", $key, $value);
}

输出:

1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
10 9
11 10

生成器Generator

以上就是迭代器了,可以看出来比较麻烦 要用就要写一个类,使用不方便,所以后来就开发了PHP生成器(Generator),只要用yield关键字的方法,返回的就是一个迭代器,可以理解为生成了一个迭代器。

生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。
https://www.php.net/manual/zh/language.generators.overview.php

一个生成器例子:

function xrange($start, $limit, $step = 1) {
    for ($i = $start; $i <= $limit; $i += $step) {
        yield $i + 1 => $i;
    }
}

使用这个生成的迭代器:

foreach (xrange(0, 10, 1) as $key => $value) {
    printf("%d %d\n", $key, $value);
}

输出:

1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
10 9
11 10

每次迭代,执行到yield关键字时,生成迭代器就会把控制流程交还给调用者,当调用者再次执行迭代或者执行迭代器的next方法时,生成迭代器才会重新运行到yield关键字处。另外,生成迭代器generator比迭代器Iterator多了两个方法send、throw,这里暂不展开。

生成器/迭代器的优势

  1. yield的可中断性。
    就说上面这个例子,foreach每一次循环,迭代器就运行一次,然后printf打印出结果或者做其他的处理。
    这样相当于把一个大的作业切片了,就算调用xrange时最大值设置为一个很大的数字,运行起来也不会有任何内存压力,因为每一次运行都由yield中断并把值返回了,然后foreach收到值之后就处理了。
  2. 生成器新增的send方法。
    协程会用到,这里暂不展开。

翻GitHub时发现有网友实现了一个rpc调度器,里面就用到了迭代器,代码不多 感觉挺不错的,这里分享出来:https://github.com/ybc429710096/scheduler

参考资料

http://www.laruence.com/2015/05/28/3038.html
https://learnku.com/articles/1430/single-php-generator-complete-knowledge-generator-implementation-process
https://www.php.net/manual/zh/language.generators.overview.php
https://segmentfault.com/a/1190000015644298
https://segmentfault.com/a/1190000012334856

发布了116 篇原创文章 · 获赞 12 · 访问量 99万+

猜你喜欢

转载自blog.csdn.net/u012628581/article/details/100543887
今日推荐