python的生成器和迭代器问题

发布于 2022-09-02 00:24:54 字数 113 浏览 12 评论 0

想彻底搞清楚这两个python重要的方法
python的生成器和迭代器的意义?相同点和不同点?
生成器的简单使用demo 、迭代器的简单使用demo
各自适合的使用场景?
谢谢 请仔细说明

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

行雁书 2022-09-09 00:24:54

迭代器生成器是两个概念,在概念上,他们没有重叠,也就是说,没有相同点

我简单概述一下:

  • 迭代器,其实就是可以用来迭代容器,比如,一个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).

关于使用场景,其实上面已经提到了,如果想知道更具体的,那么,赞我:)

冷夜 2022-09-09 00:24:54

在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() 

关于生成器,你需要用到yield或者生成器表达式;

生成器的应用场景主要在懒求值和数据生成,假设某个逻辑中,你需要0~300w个随机数,你有两种选择:

  1. 一次性生成300w随机数,然后放置在list或者某个地方中。

  2. 每次需要时临时生成一个(使用生成器)

def next_random_num():
    while True:
        yield random.randint()
        
for line in open('txtfile'):
    print next_random_num + int(line.strip())

在上面代码中,文件有多少行则临时生成多少个随机数;

橘亓 2022-09-09 00:24:54

建议还是完整的阅读下《流畅的python》,会更深地理解。我以前看了廖雪峰之类的解答。还是很不清楚。但流畅的python把这个问题系统讲了,比如为什么实现了__iter__的对象就是可迭代的,为什么迭代器要实现__next__方法。
你可以先去看下书上的示例 14.4,怎么从基础实现一个迭代器。代码如下:(还是建议完整看下这书)

“import re
import reprlib

RE_WORD = re.compile('\w+')


class Sentence:

    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __repr__(self):
        return 'Sentence(%s)' % reprlib.repr(self.text)

    def __iter__(self):  ➊
        return SentenceIterator(self.words)  ➋


class SentenceIterator:

    def __init__(self, words):
        self.words = words  ➌
        self.index = 0  ➍

    def __next__(self):
        try:
            word = self.words[self.index]  ➎
        except IndexError:
            raise StopIteration()  ➏
        self.index += 1  ➐
        return word  ➑

    def __iter__(self):  ➒
        return self
”

摘录来自: [巴西] Luciano Ramalho. “流畅的Python。” Apple Books. 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文