PHP7中生成器的新特性:生成器委托( yield-from )&返回值(return-value)
这篇文章给大家介绍的内容是关于PHP7中生成器的新特性:生成器委托( yield-from )&返回值(return-value),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
生成器委托
简单地翻译官方文档的描述:
PHP7中,通过生成器委托(yield from),可以将其他生成器、可迭代的对象、数组委托给外层生成器。外层的生成器会先顺序 yield 委托出来的值,然后继续 yield 本身中定义的值。
利用 yield from 可以方便我们编写比较清晰生成器嵌套,而代码嵌套调用是编写复杂系统所必需的。
上例子:
<?php function echoTimes($msg, $max) { for ($i = 1; $i <= $max; ++$i) { echo "$msg iteration $i\n"; yield; } } function task() { yield from echoTimes('foo', 10); // print foo ten times echo "---\n"; yield from echoTimes('bar', 5); // print bar five times } foreach (task() as $item) { ; }
以上将输出:
foo iteration 1 foo iteration 2 foo iteration 3 foo iteration 4 foo iteration 5 foo iteration 6 foo iteration 7 foo iteration 8 foo iteration 9 foo iteration 10 --- bar iteration 1 bar iteration 2 bar iteration 3 bar iteration 4 bar iteration 5
自然,内部生成器也可以接受它的父生成器发送的信息或者异常,因为 yield from 为父子生成器建立一个双向的通道。不多说,上例子:
<?php function echoMsg($msg) { while (true) { $i = yield; if($i === null){ break; } if(!is_numeric($i)){ throw new Exception("Hoo! must give me a number"); } echo "$msg iteration $i\n"; } } function task2() { yield from echoMsg('foo'); echo "---\n"; yield from echoMsg('bar'); } $gen = task2(); foreach (range(1,10) as $num) { $gen->send($num); } $gen->send(null); foreach (range(1,5) as $num) { $gen->send($num); } //$gen->send("hello world"); //try it ,gay
输出和上个例子是一样的。
生成器返回值
如果生成器被迭代完成,或者运行到 return 关键字,是会给这个生成器返回值的。
可以有两种方法获取这个返回值:
使用 $ret = Generator::getReturn() 方法。
使用 $ret = yield from Generator() 表达式。
上例子:
<?php function echoTimes($msg, $max) { for ($i = 1; $i <= $max; ++$i) { echo "$msg iteration $i\n"; yield; } return "$msg the end value : $i\n"; } function task() { $end = yield from echoTimes('foo', 10); echo $end; $gen = echoTimes('bar', 5); yield from $gen; echo $gen->getReturn(); } foreach (task() as $item) { ; }
输出结果就不贴了,想必大家都猜到。
可以看到 yield from 和 return 结合使得 yield 的写法更像平时我们写的同步模式的代码了,毕竟,这就是 PHP 出生成器特性的原因之一呀。
一个非阻塞的web服务器
现在我们利用 PHP7 中的这两个新特性重写这个 web 服务器,只需要 100 多行代码。
代码如下:
<?php class CoSocket { protected $masterCoSocket = null; public $socket; protected $handleCallback; public $streamPoolRead = []; public $streamPoolWrite = []; public function __construct($socket, CoSocket $master = null) { $this->socket = $socket; $this->masterCoSocket = $master ?? $this; } public function accept() { $isSelect = yield from $this->onRead(); $acceptS = null; if ($isSelect && $as = stream_socket_accept($this->socket, 0)) { $acceptS = new CoSocket($as, $this); } return $acceptS; } public function read($size) { yield from $this->onRead(); yield ($data = fread($this->socket, $size)); return $data; } public function write($string) { yield from $this->onWriter(); yield fwrite($this->socket, $string); } public function close() { unset($this->masterCoSocket->streamPoolRead[(int)$this->socket]); unset($this->masterCoSocket->streamPoolWrite[(int)$this->socket]); yield ($success = @fclose($this->socket)); return $success; } public function onRead($timeout = null) { $this->masterCoSocket->streamPoolRead[(int)$this->socket] = $this->socket; $pool = $this->masterCoSocket->streamPoolRead; $rSocks = []; $wSocks = $eSocks = null; foreach ($pool as $item) { $rSocks[] = $item; } yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout)); return $num; } public function onWriter($timeout = null) { $this->masterCoSocket->streamPoolWrite[(int)$this->socket] = $this->socket; $pool = $this->masterCoSocket->streamPoolRead; $wSocks = []; $rSocks = $eSocks = null; foreach ($pool as $item) { $wSocks[] = $item; } yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout)); return $num; } public function onRequest() { /** @var self $socket */ $socket = yield from $this->accept(); if (empty($socket)) { return false; } $data = yield from $socket->read(8192); $response = call_user_func($this->handleCallback, $data); yield from $socket->write($response); return yield from $socket->close(); } public static function start($port, callable $callback) { echo "Starting server at port $port...\n"; $socket = @stream_socket_server("tcp://0.0.0.0:$port", $errNo, $errStr); if (!$socket) throw new Exception($errStr, $errNo); stream_set_blocking($socket, 0); $coSocket = new self($socket); $coSocket->handleCallback = $callback; function gen($coSocket) { /** @var self $coSocket */ while (true) yield from $coSocket->onRequest(); } foreach (gen($coSocket) as $item){}; } } CoSocket::start(8000, function ($data) { $response = <<<RES HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 12 Connection: close hello world! RES; return $response; });
相关文章推荐:
以上是PHP7中生成器的新特性:生成器委托( yield-from )&返回值(return-value)的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

PHP和Python各有优势,选择应基于项目需求。1.PHP适合web开发,语法简单,执行效率高。2.Python适用于数据科学和机器学习,语法简洁,库丰富。

PHP是一种广泛应用于服务器端的脚本语言,特别适合web开发。1.PHP可以嵌入HTML,处理HTTP请求和响应,支持多种数据库。2.PHP用于生成动态网页内容,处理表单数据,访问数据库等,具有强大的社区支持和开源资源。3.PHP是解释型语言,执行过程包括词法分析、语法分析、编译和执行。4.PHP可以与MySQL结合用于用户注册系统等高级应用。5.调试PHP时,可使用error_reporting()和var_dump()等函数。6.优化PHP代码可通过缓存机制、优化数据库查询和使用内置函数。7

PHP和Python各有优势,选择依据项目需求。1.PHP适合web开发,尤其快速开发和维护网站。2.Python适用于数据科学、机器学习和人工智能,语法简洁,适合初学者。

PHP在电子商务、内容管理系统和API开发中广泛应用。1)电子商务:用于购物车功能和支付处理。2)内容管理系统:用于动态内容生成和用户管理。3)API开发:用于RESTfulAPI开发和API安全性。通过性能优化和最佳实践,PHP应用的效率和可维护性得以提升。

PHP仍然具有活力,其在现代编程领域中依然占据重要地位。1)PHP的简单易学和强大社区支持使其在Web开发中广泛应用;2)其灵活性和稳定性使其在处理Web表单、数据库操作和文件处理等方面表现出色;3)PHP不断进化和优化,适用于初学者和经验丰富的开发者。

PHP主要是过程式编程,但也支持面向对象编程(OOP);Python支持多种范式,包括OOP、函数式和过程式编程。PHP适合web开发,Python适用于多种应用,如数据分析和机器学习。

PHP适合web开发,特别是在快速开发和处理动态内容方面表现出色,但不擅长数据科学和企业级应用。与Python相比,PHP在web开发中更具优势,但在数据科学领域不如Python;与Java相比,PHP在企业级应用中表现较差,但在web开发中更灵活;与JavaScript相比,PHP在后端开发中更简洁,但在前端开发中不如JavaScript。

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。
