Python之路:迭代器和yield生成器

一、迭代器

对于Python 列表的 for 循环,他的内部原理:查看下一个元素是否存在,如果存在,则取出,如果不存在,则报异常 StopIteration。(python内部对异常已处理)

使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销

比如要逐行读取一个文件的内容,利用readlines()方法,我们可以这么写:

for line in open("test.txt").readlines():
print line

这样虽然可以工作,但不是最好的方法。因为他实际上是把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了。

利用file的迭代器,我们可以这样写:
for line in open("test.txt"):   #use file iterators
print line

这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行。

 

二、生成器

1、range不是生成器 和 xrange 是生成器

>>> print range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print xrange(10)
xrange(10)

生成器内部基于yield创建,

PS:range会在内存中创建所有指定的数字,而xrange不会立即创建,只有在迭代循环时,才去创建每个数组,从而不避免内存浪费

练习:
有如下列表: [13, 22, 6, 99, 11] 请按照一下规则计算: 13 和 22 比较,将大的值放在右侧,即:[13,22,99,11,88,44] 22 和 99 比较,将大的值放在右侧,即:[13,22,99,11,88,44] 99 和 11 比较,将大的值放在右侧,即:[13,22,99,11,88,44]
等…
 
li = [13,22,99,11,88,44]

for m in range(len(li)-1):
for n in range(m+1, len(li)):
if li[m]> li[n]:
temp = li[n]
li[n] = li[m]
li[m] = temp
print li

2、文件操作的 read 和 xreadlinex 的的区别

    read会读取所有内容到内存

    xreadlines则只有在循环迭代时才获取

# 基于next自定义生成器NReadlinesdef NReadlines():

    with open('log','r') as f:
        while True:
            line = f.next()
            if line:
                yield line
            else:
                return

for i in NReadlines():
    print i

# 基于seek和tell自定义生成器NReadlines
def NReadlines():
    with open('log','r') as f:
        seek = 0
        while True:
            f.seek(seek)
            data = f.readline()
            if data:
                seek = f.tell()
                yield data
            else:
                return

for item in NReadlines():
    print item

    yield关键字用来定义生成器(Generator),其具体功能是可以当return使用,从函数里返回一个值,不同之处是用yield返回之后,可以让函数从上回yield返回的地点继续执行。也就是说,yield返回函数,交给调用者一个返回值,然后再“瞬移”回去,让函数继续运行, 直到吓一跳yield语句再返回一个新的值

(用于做数据库的链接池)

clipboard

 

 
 
友情链接:http://www.cnblogs.com/wupeiqi/articles/4911365.html  武sir
posted @ 2015-12-18 17:23  yjycess  阅读(215)  评论(0编辑  收藏  举报