PHP 迭代生成器 yield
迭代生成器
生成器的核心是一个 yield
关键字,一个生成器函数看起来像是一个普通的函数,不同的是:普通函数返回一个值,而一个生成器可以 yield
生成许多他需要的值。生成器函数被调用时,返回的是一个可以遍历的对象。
yield
和 return
有点类似,不过不同的是,return
会返回值并且终止代码的运行,而 yield
会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。
1 | function gen_one_tow_three() |
输出
1 | 1 (0) { } |
调用 gen_one_tow_three()
的时候,里面的代码并没有真正的执行,而是返回一个生成器对象 $generator = Generator Object()
$generator instanceof Iterator
说明 Generator
实现了 Iterator
接口,可以用 foreach
进行遍历,每次遍历都会隐式调用 current()
、next()
、key()
、valid()
等方法。(Generator
类中的方法)
处理大数据
下面通过实现一个 xrange
函数来简单说明:
1 | function xrange ($start, $end, $step = 1) |
上面这个 xrange()
函数提供了和 php
的内建函数 range()
一样的功能,但不同的是 range()
函数返回的是一个包含值从 1
到 100w
的数组,而 xrange()
函数返回的是依次输出这些值得一个迭代器,而不会真正以数组形式返回。
这种方法的优点是显而易见的,它可以让你在处理大数据集合的时候不用一次性加载到内存中。甚至你可以处理无限大的数据流
处理大文件
老式读取
1 | function readLocalFile($fileName) |
yield 读取方式
1 | function readYieldFile($fileName) |
为了便于测试,写一个读取内存的辅助函数
1 | function formatBytes($bytes) |
老式读取方式测试
1 | // all.zip 是一个 158M 的压缩文件 |
yield 读取方式测试
1 | $lines = readYieldFile('./all.zip'); |
总结
使用老式读取,返回的是一个包含每行数据的数组,而 yield
方式则返回的事宜个迭代器,而不会以真正的数组返回。
这种方法的有点可以让你在处理大数据集合的时候不用一次性加载到内存中,甚至可以处理无限大的数据流。