迭代和迭代器
迭代是指反复执行一个过程,每执行一次叫做迭代一次。比如普通的遍历便是迭代:
$arr = [1, 2, 3, 4, 5];foreach($arr as $key => $value) {    echo $key . ' => ' . $value . "\n";}
我们可以看到通过foreach对数组遍历并迭代输出其内容。在foreach内部,每次迭代都会将当前的元素的值赋给$value并将数组的指针移动指向下一个元素为下一次迭代做准备,从而实现顺序遍历。像这样能够让外部的函数迭代自己内部数据的接口就是迭代器接口,对应的那个被迭代的自己就是迭代器对象。

PHP提供了统一的迭代器接口:
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接口,我们可以自行的决定如何遍历对象。

foreach之所以能工作,是因为这些集合类都实现了Iterable接口,该接口中定义了Iterator迭代器的产生方法,并且foreach就是通过Iterable接口在序列中进行移动。

yield和生成器
相比较迭代器,生成器提供了一种更容易的方法来实现简单的对象迭代,性能开销和复杂性都大大降低。 一个生成器函数看起来像一个普通的函数,不同的是普通函数返回一个值,而生成器可以yield生成许多个值,并且每一次的yield只是暂停当前的执行状态,当下次调用生成器函数时,PHP会从上次暂停的状态继续执行下去。 我们在使用生成器的时候可以像关联数组那样指定一个键名对应生成的值。如下生成一个键值对与定义一个关联数组相似。
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";}
概念理解
首先明确一个概念:生成器yield关键字不是返回值,他的专业术语叫产出值,只是生成一个值。实际上生成器函数返回的是一个Generator对象,这个对象不能通过new实例化,并且实现了Iterator接口。 那么代码中 foreach 循环的是什么?PHP在使用生成器的时候,会返回一个 Generator 类的对象。 foreach 可以对该对象进行迭代,每一次迭代,PHP会通过 Generator 实例计算出下一次需要迭代的值。这样 foreach 就知道下一次需要迭代的值了。 而且,在运行中 for 循环执行后,会立即停止。等待 foreach 下次循环时候再次和 for 索要下次的值的时候,循环才会再执行一次,然后立即再次停止。直到不满足条件不执行结束。 生成器优点 生成器会对PHP应用的性能有非常大的影响 PHP代码运行时节省大量的内存 比较适合计算大量的数据 实际开发应用:读取超大文件
PHP开发很多时候都要读取大文件,比如csv文件、text文件,或者一些日志文件。这些文件如果很大,比如5个G。这时,直接一次性把所有的内容读取到内存中计算不太现实。使用生成器读取文件,第一次读取了第一行,第二次读取了第二行,以此类推,每次被加载到内存中的文字只有一行,大大的减小了内存的使用。
<?php

header("content-type:text/html;charset=utf-8");

function readTxt()

{

    # code...

    $handle = fopen("./test.txt", 'rb');

    while (feof($handle)===false) {

        # code...

        yield fgets($handle);

    }

    fclose($handle);

}

foreach (readTxt() as $key => $value) {

    # code...

    echo $value.'<br />';

}
 

PHP 迭代器和生成器的更多相关文章

  1. Python 从零学起(纯基础) 笔记 之 迭代器、生成器和修饰器

    Python的迭代器. 生成器和修饰器 1. 迭代器是访问集合元素的一种方式,从第一个到最后,只许前进不许后退. 优点:不要求事先准备好整个迭代过程中的所有元素,仅仅在迭代到某个元素时才计算该元素,而 ...

  2. Python之模块,迭代器与生成器

    本节涉及内容: 1. 迭代器和生成器 2. 递归 3. 字符串格式化 4. 模块 内置模块 自定义模块 第三方模块 5. 序列化的模块 json pickle (一). 迭代器和生成器: 迭代器:  ...

  3. Python之迭代器和生成器

    Python 迭代器和生成器 迭代器 Python中的迭代器为类序列对象(sequence-like objects)提供了一个类序列的接口,迭代器不仅可以对序列对象(string.list.tupl ...

  4. python学习笔记四 迭代器,生成器,装饰器(基础篇)

    迭代器 __iter__方法返回一个迭代器,它是具有__next__方法的对象.在调用__next__方法时,迭代器会返回它的下一个值,若__next__方法调用迭代器 没有值返回,就会引发一个Sto ...

  5. 【Python】迭代器、生成器、yield单线程异步并发实现详解

    转自http://blog.itpub.net/29018063/viewspace-2079767 大家在学习python开发时可能经常对迭代器.生成器.yield关键字用法有所疑惑,在这篇文章将从 ...

  6. 15.python的for循环与迭代器、生成器

    在前面学习讲完while循环之后,现在终于要将for循环这个坑填上了.之所以拖到现在是因为for循环对前面讲过的序列.字典.集合都是有效的,讲完前面的内容再来讲for循环会更加容易上手. 首先,for ...

  7. Python: 迭代器与生成器小结

    迭代器与生成器的区别: 1. 迭代器由Class对象创建. 生成器由包含yield表达的Function对象或者Generator Expression创建. 2. 迭代器的原理: (1)由Itera ...

  8. Python中的迭代器和生成器

    本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述: 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后 ...

  9. Python可迭代对象、迭代器和生成器

    Python可迭代对象.迭代器和生成器 python 函数 表达式 序列 count utf-8 云栖征文 python可迭代对象 python迭代器 python生成器 摘要: 8.1 可迭代对象( ...

  10. Python高手之路【九】python基础之迭代器与生成器

    迭代器与生成器 1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外 ...

随机推荐

  1. java代码示例(6-2)

    创建Customer.java /*** * 需求分析:创建客户类 * @author chenyanlong * 日期:2017/10/15 */ package com.hp.test06; pu ...

  2. spring校验注解

    @Null   被注释的元素必须为 null @NotNull    被注释的元素必须不为 null @AssertTrue     被注释的元素必须为 true @AssertFalse    被注 ...

  3. JavaSE学习总结(七)—— 集合

    一.为什么需要集合 如果要将100个学生成绩存放到程序中,怎么做? 首先想到是数组 int[] scores=new int[100]; 然而,长度是固定的,比如是101个学生成绩,这个数组就不能用了 ...

  4. mySQL数值类型的取值范围

    如下图,int最大为2145483647,手机号码应该用bigint

  5. jdk1.6 反射性能对比【原】

    ReflectPerformance.java package aaa.bbb.ccc; import java.lang.reflect.Method; public class ReflectPe ...

  6. bzoj千题计划301:bzoj4259: 残缺的字符串

    https://www.lydsy.com/JudgeOnline/problem.php?id=4259 令通配符=0 f[i+m-1]=Σ (a[i+j]-b[m-1-j])^2 * a[i+j] ...

  7. luogu 1972 小H的项链 莫队

    1.莫队算法 TLE 80 #include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<=y;i++) usi ...

  8. golang string int int64转换

    #string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt(string, 10, 6 ...

  9. Linux - svn 操作

    --force # 强制覆盖 /usr/bin/svn --username user --password passwd co $Code ${SvnPath}src/ # 检出整个项目 /usr/ ...

  10. 第18月第2天 ios博客

    1. github https://githuber.cn/search?language=Objective-C https://www.jianshu.com/u/815d10a4bdce htt ...