生成器和列表解析总结及测试

一边循环一边计算的机制,称之为生成器generator;生成器的创建具有两种方式:

1、 第一种是直接使用生成器表达式,也就是将列表解析的中括号修改为圆括号即可

2、第二种是在一个函数的定义中包含yield关键字,那么这个函数也就是一个生成器

生成器是特定的函数,允许返回一个值,然后暂停代码的执行,稍后回复,在使用生成器的时候,内存可以使用更友好的结构,如下:

>>> sum(len(word) for line in open('kel.log') for word in line.split()) #注意在使用的时候先新建一个文件为kel.log
31
生成器表达式就像是一个懒惰的列表解析,只有在循环的时候,才会真正的去进行计算,从而比较节省内存。

[root@python 49]# cat getlongest.py  #写的一个脚本,直接执行即可,在这里使用的是生成器表达式来返回一个文件中最长的行数
#!/usr/bin/env python
'''
this is get the file longest line
'''
lo = max((len(line) for line in open('kel.log') ))
print lo
[root@python 49]# cat kel.log  #文件名称为kel.log,文件内容如下所示
this is the test file of the generator
this is anoter line
linie
there is a lone line in the last line,for the generator

以上表示是直接使用生成器表达式来生成一个生成器generator。

python的生成器:生成器就是一个具有yield语句的函数,一个函数或者子程序只返回一次,生成器能暂停执行并返回一个中间结果,这也就是yield关键字的作用。


做了一个测试,分别使用列表解析的方式和生成器的方式来测试执行时间和使用的内存情况:

import time
start_time = time.time()
lo = max((len(line) for line in open('kel.log') )) #使用列表解析
print lo
end_time = time.time()
print end_time-start_time #打印程序执行的时间

测试结果如下:

[root@python 49]# du -sh
1.1G	.
[root@python 49]# python getlongest.py   #使用的内存大概为900多M,基本将所有的数据都保存在cache当中
479
9.72497296333 #使用的时间单位为妙
使用列表解析来进行测试:

start_time = time.time()
lo = max([len(line) for line in open('kel.log') ]) #使用列表解析来直接生成一个列表
print lo
end_time = time.time()
print end_time-start_time

测试结果如下:

[root@python 49]# python getlongest.py  #使用的内存也差不多也是900多M
479
10.0769059658#使用时间为秒
占用内存情况如下:

[root@python ~]# vmstat 1 -S M  3
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0    196      0    730    0    0    50     6   13    8  0  0 100  0  0	
 0  0      0    196      0    730    0    0     0     0   18    7  0  0 100  0  0	
 0  0      0    196      0    730    0    0     8     0   26   28  0  0 97  3  0	
可以看倒memory中的内存数量大量减少,然后cache中占用的数量变大,在进行清除缓存的时候,使用命令如下:

[root@python ~]# echo 1 > /proc/sys/vm/drop_caches  #表示仅清除页面缓存,pagecache


从以上可以看到,无论是列表解析还是生成器表达式都会将所有的数据导入到内存中。。。说好的生成器表达式节省内存呢???

一个生成器的函数的例子如下,使用了yield关键字的函数为生成器generator:

#!/usr/bin/env python
def counter(start_at=0):
    count = start_at
    while True:
        val = (yield count)
        if val is not None:
            count = val
        else:
            count += 1
使用的时候如下:

count = counter()
    print count.next()
    print count.next()
    count.send(9)
    print count.next()
    print count.next()
    count.close()
在其中send方法表示进行重置生成器,而close方法是关闭生成器,在此调用next方法的时候会出现StopIteration的异常


其中生成器和迭代器的区别在于:生成器是一个函数,具有yield关键词,并且在使用完之后可以重新进行遍历循环;而迭代器只能使用一次,只能向后,不能向前。










for linux and python
原文地址:https://www.cnblogs.com/kellyseeme/p/5525048.html