你对生成器了解多少?

4 篇文章 0 订阅

最近在学习Python的时候了解到生成器(generator)的概念,觉得挺有趣的,顺便又学习了下PHP的生成器,这里就记录一下吧~

 

 

生成器,其实可以理解为是数组,但是既然它叫生成器,那肯定是和数组是有区别的。具体区别是啥呢?

 

我们知道,在我们声明一个数组的时候,程序会开辟一个内存来保存这个数组的数据,如果这个数组特别大,比如rang(1,1000000),这将会占用100M的内存空间,显然是不合适的。而且有时候我们可能只需要数组的前几个数据,并不一定要获取到所有的数据,这时候,生成器就派上用场了。

 

生成器可以实现我们在循环数据的时候,循环到哪个位置的数据再去取这个数据。之所以可以实现,是因为生成器里是保存了,数组数据的推算算法,可以理解为是一个迭代器,通过这个迭代器实现在循环的过程中,不断的推算出后面的数据,从而输出给我们。在数据显示上和循环一个数组是一样的效果~

 

 

下面是PHP手册上对生成器的解释:

生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。

生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。相反,你可以写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值。

 

我们分别用Python和PHP来实现下生成器

 

Python

我们先输出一个list

L = [x * x for x in range(10)]print(L)#输出[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

 

下面我们来实现一个生成器

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

g = (x * x for x in range(10))print(g)#如果我们直接打印g 将会输出如下的对象,里面存的其实是generator的迭代对象<generator object <genexpr> at 0x0000022392C09EB0>#如果想输出值,得用next(g)print(next(g))print(next(g))01

 

但是,用next()获取值还是很鸡肋,所以还有更好的办法来获取值。我们可以用一个for循环来获取值

for n in g:    print(n)#将会循环输出值0149162536496481

 

下面我们看一下如何用函数来实现一个生成器,其实生成器函数和普通函数基本是一样是,只是普通函数是通过return来返回值,而生成器是通过yield关键字来返回值。我们以实现斐波那契数列的函数来说明:

def fib(max):    n, a, b = 0, 0, 1    while n < max:        yield b        a, b = b, a + b        n = n + 1    return 'done'for n in fib(6):    print(n)    #输出112358

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:

f = fib(6)while True:    try:        k = next(f)        print('k:',k)    except StopIteration as e:        print('generator return value:',e.value)        break#输出k: 1k: 1k: 2k: 3k: 5k: 8generator return value: done    

以上就是用Python实现生成器

 

PHP

PHP的生成器和Python的实现基本是一样的,也是通过yield关键字来实现。

 

我们来将PHP里的range()函数用生成器的方式实现:

<?phpfunction xrange($start, $limit, $step = 1) {    if ($start < $limit) {        if ($step <= 0) {            throw new LogicException('Step must be +ve');        }        for ($i = $start; $i <= $limit; $i += $step) {            yield $i;        }    } else {        if ($step >= 0) {            throw new LogicException('Step must be -ve');        }        for ($i = $start; $i >= $limit; $i += $step) {            yield $i;        }    }}/*  * 注意下面range()和xrange()输出的结果是一样的。 */echo 'Single digit odd numbers from range():  ';foreach (range(1, 9, 2) as $number) {    echo "$number ";}echo "\n";echo 'Single digit odd numbers from xrange(): ';foreach (xrange(1, 9, 2) as $number) {    echo "$number ";}?>

以上代码会有如下输出:

Single digit odd numbers from range():  1 3 5 7 9 Single digit odd numbers from xrange(): 1 3 5 7 9

 

总结:

Python和PHP中的生成器都是通过yield关键字来实现的,而且一般都是用在循环中。在循环大数组的时候会很大的提升性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值