yield

PHP性能优化利器:生成器 yield理解

杀马特。学长 韩版系。学妹 提交于 2019-11-29 01:42:34
如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生。但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明显。但是,生成器功能的确非常有用。 优点 直接讲概念估计你听完还是一头雾水,所以我们先来说说优点,也许能勾起你的兴趣。那么生成器有哪些优点,如下: 生成器会对PHP应用的性能有非常大的影响 PHP代码运行时节省大量的内存 比较适合计算大量的数据 那么,这些神奇的功能究竟是如何做到的?我们先来举个例子。 概念引入 首先,放下生成器概念的包袱,来看一个简单的PHP函数: function createRange($number){ $data = []; for($i=0;$i<$number;$i++){ $data[] = time(); } return $data; } 这是一个非常常见的PHP函数,我们在处理一些数组的时候经常会使用。这里的代码也非常简单: 我们创建一个函数。 函数内包含一个 for 循环,我们循环的把当前时间放到 $data 里面 for 循环执行完毕,把 $data 返回出去。 下面没完,我们继续。我们再写一个函数,把这个函数的返回值循环打印出来: $result = createRange(10); // 这里调用上面我们创建的函数 foreach($result as

php生成器使用总结

烈酒焚心 提交于 2019-11-29 01:42:19
一般我们在迭代一组数据的时候,需要创建一个数据,如果数组很大,则会消耗很大性能,甚至造成内存不足抛出error 比如: //Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in D:\php\test\index.php on line 5 range(1, 100000000); PHP5.5引入了迭代生成器的概念,迭代的概念早就在PHP有了,但是迭代生成器是PHP的一个新特性,这跟python3中的迭代生成器类似,看看PHP5.5的迭代生成器如何定义。 以下示例实现了生成器,每当产生一个数组元素则用yield关键词返回,并且执行函数暂停,当执行函数next方法时,则会从上一次被yield的位置开始继续执行,如下例子,只会产生中间变量$i function xrange($start, $limit, $step = 1) { for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } foreach (xrange(1, 9, 1) as $number) { echo "$number "; } 这里的xrange是一个迭代,功能和range是一样的,如果使用range函数的话

Php5.5新特性 Generators详解

筅森魡賤 提交于 2019-11-29 01:41:45
在 PHP5.5.0 版本中,新增了生成器 (Generators) 特性,用于简化实现迭代器接口 (Iterator) 创建简单的迭代器的复杂性。 通过生成器,我们可以轻松的使用 foreach 迭代一系列的数据,而不需要事先在内存中构建要被迭代的对象,大大减少了内存开销。 当生成器函数被调用的时候,它会返回一个可迭代的对象,当对该对象进行迭代的时候,PHP将会在需要的时候调用生成器函数,并且在生成器使用新增的关键字 yield 产生一个新的值的时候,保存迭代器内部的状态。迭代器没有新的值需要产生的时候,生成器函数就可以直接退出,外部函数继续执行。 注意,在生成器函数中,不能使用 return 语句返回值,使用 return 返回值的话会产生编译器错误。但是,使用空的 return 是可以的,它会使迭代器终止。 生成器函数与普通函数一样的,唯一的区别函数内使用了 yield 关键字。 yield 语句可以说是生成器函数的核心,简单来说, yield 就像 return 语句一样,区别是 return 语句返回后函数就结束了,而使用 yield 返回后,只是暂停了函数的执行,转到外部函数继续执行,下次调用生成器函数的时候,继续执行生成器函数内部的代码。 一个简单的例子 - 生成器版本的range函数 一个简单的例子是使用 foreach 迭代函数 range 的返回值,如果调用的是

php yield

怎甘沉沦 提交于 2019-11-29 01:41:25
yield特性一般跟生成器generator紧密联系在一起 Generator implements Iterator { /* Methods */ public mixed current ( void ) public mixed key ( void ) public void next ( void ) public void rewind ( void ) public mixed send ( mixed $value ) public mixed throw ( Exception $exception ) public bool valid ( void ) public void __wakeup ( void ) } 注释:send()方法主要用于发送数据给当前yield,即yield被当作一个值被替换,且继续执行下一个yield,相当于next加current 所谓Generators, 我们以下称为”生成器”, 是一种可以返回迭代器的生成器. 呵呵, 这话有点绕, 让我们看看一个代码, 在没有迭代器之前, 如果我们遍历一个动态生成的数组: <?php function return_array () { $array = dummy (); //计算全部数组内容 return $array ; } foreach ( return_array () as

PHP的学习--生成器Generators

爷,独闯天下 提交于 2019-11-29 01:41:11
生成器总览 (PHP 5 >= 5.5.0, PHP 7) 生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。 生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。相反,你可以写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值。 一个简单的例子就是使用生成器来重新实现 range() 函数。 标准的 range() 函数需要在内存中生成一个数组包含每一个在它范围内的值,然后返回该数组, 结果就是会产生多个很大的数组。 比如,调用 range(0, 1000000) 将导致内存占用超过 100 MB。 做为一种替代方法, 我们可以实现一个 xrange() 生成器, 只需要足够的内存来创建 Iterator 对象并在内部跟踪生成器的当前状态,这样只需要不到1K字节的内存。 Example #1 将 range() 实现为生成器 <?php function xrange($start, $limit, $step = 1) { if ($start < $limit) { if ($step <= 0) { throw new

What are real life applications of yield?

可紊 提交于 2019-11-29 01:41:04
I know what yield does, and I've seen a few examples, but I can't think of real life applications, have you used it to solve some specific problem? (Ideally some problem that cannot be solved some other way) Ash I realise this is an old question (pre Jon Skeet?) but I have been considering this question myself just lately. Unfortunately the current answers here (in my opinion) don't mention the most obvious advantage of the yield statement. The biggest benefit of the yield statement is that it allows you to iterate over very large lists with much more efficient memory usage then using say a

Ruby on rails: Yielding specific views in a specific places in the layout

蹲街弑〆低调 提交于 2019-11-29 01:29:29
问题 If I have one <%= yield %> tag then all my views render in the same place in the layout. Can I have different <%= yield %> tags for different views? Is so how do I do this? Thanks 回答1: Look into ActionView::Helpers::CaptureHelper. You can do something like this in your views: <% content_for :sidebar do %> <!-- sidebar content specific to this page --> <% end %> This will run the template inside the content_for block, but will not output as part of the regular template yield buffer, it will be

Which is generally faster, a yield or an append?

纵饮孤独 提交于 2019-11-29 01:04:00
问题 I am currently in a personal learning project where I read in an XML database. I find myself writing functions that gather data and I'm not sure what would be a fast way to return them. Which is generally faster: yield s, or several append() s within the function then return the ensuing list ? I would be happy to know in what situations where yield s would be faster than append() s or vice-versa. 回答1: yield has the huge advantage of being lazy and speed is usually not the best reason to use

Python: yield and yield assignment

拥有回忆 提交于 2019-11-29 00:55:21
问题 How does this code, involving assignment and the yield operator, work? The results are rather confounding. def test1(x): for i in x: _ = yield i yield _ def test2(x): for i in x: _ = yield i r1 = test1([1,2,3]) r2 = test2([1,2,3]) print list(r1) print list(r2) Output: [1, None, 2, None, 3, None] [1, 2, 3] 回答1: The assignment syntax ("yield expression") allows you to treat the generator as a rudimentary coroutine. First proposed in PEP 342 and documented here: https://docs.python.org/2

How to Pythonically yield all values from a list?

夙愿已清 提交于 2019-11-29 00:54:23
Suppose I have a list that I wish not to return but to yield values from. What is the most pythonic way to do that? Here is what I mean. Thanks to some non-lazy computation I have computed the list ['a', 'b', 'c', 'd'] , but my code through the project uses lazy computation, so I'd like to yield values from my function instead of returning the whole list. I currently wrote it as following: my_list = ['a', 'b', 'c', 'd'] for item in my_list: yield item But this doesn't feel pythonic to me. Use iter to create a list iterator e.g. return iter(List) though if you already have a list, you can just