PHP中trait(性状)与generator(生成器)

PHP中trait(性状)与generator(生成器)

一、trait (性状)

最近在看Josh Lockhat的《Modern PHP》,这本书很薄。但是其中给出了一个很重要的学习方法。就是写PHP程序的时候不要凡事都自己来创造,如果已经有牛人写好了组件,直接放进自己项目中用就好了,并且给出了组件的链接。这半年看技术不少,外国的程序员比较喜欢按部就班的按照规范来写程序,包括代码规范,如何保证代码的性能方面,都严格按照工具进行测试。但是我前一份工作,对于代码规范和上线规范就比较松懈。这家公司有了很大的提高,在项目组长的要求下,还开发了功能强大的上线系统。

这本书中我看到了性状,于迭代器这两个对于我来说比较新的内容。其实这两个东西都比较好理解,因此就不单独写博客介绍了,合并在一篇博客中介绍,大家看代码就好。

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

trait BandAid
{
public function __construct()
{
echo "Hello BandAid<br/>";

}

public function getName()
{
echo "Roverliang<br/>";
}
}

trait BandAid_2
{
public function hello()
{
echo "I'm BandAid_2<br/>";
}
}

class Body
{
use BandAid;
use BandAid_2;

public function __construct()
{
echo "Hello Body<br/>";
}

public function makeDance()
{
echo "Dance<br/>";
}

}

$roverliang = new Body();
$roverliang->getName();
$roverliang->makeDance();
$roverliang->hello();

结果:

Hello Body
Roverliang
Dance
I'm BandAid_2

其实PHP manual 中关于性状讲解的更为清晰:trait:性状

其中有一个需要注意点,容易犯错代码如下:

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

class TestClass
{
public static $bar;
}

class Foo1 extends TestClass {}
class Foo2 extends TestClass {}

Foo1::$bar = "hello";
Foo2::$bar = "World";

echo Foo1::$bar;
echo Foo2::$bar;

//result is
/**
* WorldWorld
*/
/*********************************************/
trait TestTrait
{
public static $bar;
}

class Foo3
{
use TestTrait;
}

class Foo4
{
use TestTrait;
}

Foo3::$bar = "Hello";
Foo4::$bar = "world";

echo Foo3::$bar;
echo Foo4::$bar;

//result
/**
* Helloworld
*/

由于这个markdown 工具没有代码折叠的功能,所以只能让大家看这么冗长的代码了。trait 是一种灵活的代码段。PHP5.4 版本才增加这个功能,所以使用的时候一定要先看下自己所使用的PHP版本。PHP文档中说了,trait是一种代码复用的方法。我对于trait理解是,trait就是一个创可贴,哪里需要了就贴上去,满足功能。trait的__construct 在使用的时候会被重写,因此使用trait的时候可以不用写构造函数。

generator(生成器)

关于生成器详细可以看官方文档:生成器总览

尤其要注意的是,生成器的版本要求是PHP 5 >= 5.5.0, PHP 7

示例如下:

<?php
header("content-type:text/html;charset=utf-8");
date_default_timezone_set('Asia/Shanghai');
$file = "./ip-to-country.csv";

function getFile($file)
{
$handler = fopen($file, 'rb');
if ($handler === false) {
throw new Exception();
}
while (!feof($handler)) {
yield fgetcsv($handler);
}
fclose($handler);
}

$stime = microtime(true);
foreach (getFile($file) as $val) {
//print_r($val); save to redis
}
$etime = microtime(true);
$exectime_1 = $etime - $stime;

function getFile_2($file)
{
$handler = fopen($file, 'rb');
if ($handler === false) {
throw new Exception();
}
while (!feof($handler)) {
fgetcsv($handler); //save to redis
}
fclose($handler);
}

$stime = microtime(true);
getFile_2($file);
$etime = microtime(true);
$exectime_2 = $etime - $stime;

echo $exectime_1;
echo "\r\n";
echo $exectime_2;
echo "\r\n";

//352.71399402618
//331.73138713837

本文测试的文件大小如下:

[root@roverliang html]# ls -lh
总用量 2.0G
-rwxr--r--. 1 jack jack 171 11月 17 13:23 Creator.php
-rwxr--r--. 1 jack jack 236 11月 17 13:27 GraphicFactory.php
-rwxr--r--. 1 jack jack 963 11月 20 07:53 index.php
-rwxr--r--. 1 root root 2.0G 11月 20 06:38 ip-to-country.csv
-rwxr--r--. 1 jack jack 243 11月 19 13:38 TextFactory.php

经过测试发现,迭代器在读取大文件时候并没有表现出其官网所宣称的那种效率。甚至比使用使用常规的逐行读取方法还要慢一点点,不过这种时间上的差距可以忽视。比第二种方式略慢,可能是因为迭代器内部的状态切换所带来的性能开销。

那么两种方式在系统内存和cpu占用上有何不同,看下图:

使用迭代器



不使用

由此可以看出,使用迭代器和不使用两者并没有明显不同。

虽然如此,还是需要了解迭代器,至少给予我们一种不同的方式来进行数据操作。

php中trait(性状)与generator(生成器)的更多相关文章

  1. ES6新特性:Javascript中Generator(生成器)

    ES6的很多特性都跟Generator扯上关系,而且实际用处比较广, 包含了任何需要异步的模块, 比如ajax, filesystem, 或者数组对象遍历等都可以用到: Generator的使用: G ...

  2. ES6中的迭代器(Iterator)和生成器(Generator)

    前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...

  3. Javascript中Generator(生成器)

    阅读目录 Generator的使用: yield yield* next()方法 next()方法的参数 throw方法() return()方法: Generator中的this和他的原型 实际使用 ...

  4. ES6中的迭代器(Iterator)和生成器(Generator)(一)

    用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...

  5. ES6笔记(5)-- Generator生成器函数

    系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...

  6. MyBatis Generator 生成器把其他数据库的同名表生成下来的问题

    [问题] 使用MyBatis Generator生成器时,发现Mapper文件中出现字段与连接数据库不符,经过查找发现该表是其他数据库的同名表的字段. [解决问题] 在构造文件中,这里是generat ...

  7. Generator生成器函数

    接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还有一种常用的解决方案,它就是Ge ...

  8. Python高级语法之:一篇文章了解yield与Generator生成器

    Python高级语法中,由一个yield关键词生成的generator生成器,是精髓中的精髓.它虽然比装饰器.魔法方法更难懂,但是它强大到我们难以想象的地步:小到简单的for loop循环,大到代替多 ...

  9. 取代Promise的Generator生成器函数

    接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还有一种常用的解决方案,它就是Ge ...

随机推荐

  1. Using AlloyTouch to control three.js 3D model

    As you can see, the above cube rotation, acceleration, deceleration stop all through the AlloyTouch ...

  2. 自己实现一个简易web服务器

    一个web服务器是网络应用中最基础的环节. 构建需要理解三个内容: 1.http协议 2.socket类 3.服务端实现原理 1.1 HTTP http请求 一般一个http请求包括以下三个部分: 1 ...

  3. 日期关联取最近日期的SQL

    SQL怎么关联,如下图A表用日期加产品编号关联B表的时候,如果日期不存在,则取之前最近一个日期的值,比如A表2012-07-31 关联B表,B表没有对应日期的,就取2012-07-30的 A表     ...

  4. 详解java定时任务

    在我们编程过程中如果需要执行一些简单的定时任务,无须做复杂的控制,我们可以考虑使用JDK中的Timer定时任务来实现.下面LZ就其原理.实例以及Timer缺陷三个方面来解析JavaTimer定时器. ...

  5. PostgreSQL隐藏字段tableoid

    问题来源: 今天群里有人问:tableoid字段在每行都有,而且一个表里面的值是重复的,这样不合理...... 因此做了一些分析: 1)创建了一个表 apple=# \d test_time Tabl ...

  6. JavaScript数组

    声明: var mycars=new Array(3) 扩号中的3也可以不写.不写即不限定数组的容量,可以无限制的向数组内添加值. 赋值: mycars[0]="Saab" 和Ja ...

  7. archlinux 加载loop模块,且设定loop设备个数

    如果loop模块没有编译进内核就要先加载loop模块 modprobe loop 然后更改/etc/modprobe.d/modprobe.conf(有些文章写是在/etc/modprobe.conf ...

  8. 【Linux命令】文件和目录操作命令

    本文主要用于常用命令的备忘,具体用法可用man查看,或查询其他资料. cd:改变工作目录 ls:列出目录的内容 mkdir:创建一个目录 cat:连接并显示指定的一个和多个文件的有关信息 cp:将给出 ...

  9. x86开启 HUGEPAGES

    HugePage,就是指的大页内存管理方式,在操作系统Linux环境中,内存是以页Page的方式进行分配,默认大小为4K,HugePage是传统4K Page的替代方案.顾名思义,是用HugePage ...

  10. CentOS下开启mysql远程连接,远程管理数据库

    当服务器没有运行php.没装phpmyadmin的时候,远程管理mysql就显得有必要了.因为在CentOS下设置的,所以标题加上了CentOS,以下的命令在debian等系统下应该也OK. mysq ...