大家讲道理2017-04-17 17:02:37
迭代器
与生成器
是两个概念,在概念上,他们没有重叠,也就是说,没有相同点。
我简单概述一下:
迭代器,其实就是可以用来迭代
的容器
,比如,一个list,tuple等.
生成器,这里的生成
指得是它可以产生迭代器
.
下面是demo:
foods = ['banana', 'hot dog', 'dumpling']
for food in foods:
print food
这里的foods
就是一个迭代器.
def send_file(file_path, size):
with open(file_path) as f:
block = f.read(BLOCK_SIZE)
while block:
yield block
block = f.read(BLOCK_SIZE)
这是一个生成器
,注意,生成器
的重点就是yield
,这里的block
就是生成器每次生成的值,可以暂时理解为相当于迭代器
中的单个元素,比如foods
中的banana
元素,而生成器的主要作用就是把大内存占用数据分次写入内存
,这样做得好处就是可以不用一次性将所有数据读入到程序中占用大量内存,并且可以在不影响使用的情况下,防止内存泄露,从而让程序使用者有更好的体验,也会让你的代码更(you)优(bi)雅(ge).
关于使用场景,其实上面已经提到了,如果想知道更具体的,那么,赞我:)
阿神2017-04-17 17:02:37
在python中,你可以将迭代器放置在for语句中,将一个对象添加迭代器特性就可以满足上面的需求;这里是我的一个例子,我们通常需要使用内存映射文件方式打开一个大文件,但是标准的mmap对象不支持迭代,也就是说像下面的代码是不能执行的:
for line in mmap.open(file_name):
print line
如果你希望可以达到这样的效果就需要借助与迭代器, 参见下面的iter和next函数;
class Mmap(object):
__slots__ = ['os', 'mmap', 'handler', 'mhandler']
def __init__(self, fname):
self.os = __import__('os', fromlist=['path'])
self.mmap = __import__('mmap')
assert self.os.path.exists(fname), 'File(%s) Not Exists !' % fname
self.handler = open(fname)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.mhandler.close()
self.handler.close()
del self.os
del self.mmap
class Reader(Mmap):
'''使用mmap打开文件,并添加iterable特性'''
def __init__(self, fname):
super(Reader, self).__init__(fname)
self.mhandler = self.mmap.mmap(self.handler.fileno(), 0, prot=self.mmap.PROT_READ)
def __iter__(self):
return self
def next(self):
line = self.mhandler.readline()
if line:
return line
else:
raise StopIteration
if __name__ == '__main__':
with Reader('./demo/simple.dat') as f: #现在就可以了
for line in f:
print line.strip()
生成器的应用场景主要在懒求值和数据生成,假设某个逻辑中,你需要0~300w个随机数,你有两种选择:
一次性生成300w随机数,然后放置在list或者某个地方中。
每次需要时临时生成一个(使用生成器)
def next_random_num():
while True:
yield random.randint()
for line in open('txtfile'):
print next_random_num + int(line.strip())
在上面代码中,文件有多少行则临时生成多少个随机数;