前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python语法-迭代器和生成器

Python语法-迭代器和生成器

作者头像
码客说
发布2021-11-29 09:21:02
1850
发布2021-11-29 09:21:02
举报
文章被收录于专栏:码客码客码客

迭代器

先看一个这样的示例

class Company:
    def __init__(self,users):
        self.users = users
        self.index = 0

    def __getitem__(self, item):
        return self.users[item]


if __name__ == "__main__":
    c = Company(["小明", "小红", "小刚"])
    for u in c:
        print(u)

这样原来的实例就可以遍历了,__getitem__有个参数item就是迭代的索引,这是因为编译器自动在内部自动生成了迭代器,相当于如下代码

from collections.abc import Iterator


class Company:
    def __init__(self, users):
        self.users = users
        self.index = 0

    def __iter__(self):
        return MyIterator(self.users)


class MyIterator(Iterator):
    def __init__(self, list):
        self.index = 0
        self.list = list

    def __next__(self):
        try:
            item = self.list[self.index]
            self.index += 1
        except IndexError:
            raise StopIteration
        return item


if __name__ == "__main__":
    c = Company(["小明", "小红", "小刚"])
    for u in c:
        print(u)

但是我们明明抛出异常了,但是并没有捕获处理啊!这是因为for in内部已经处理了

for in相当于转化为了如下代码:

class Company:
    def __init__(self, users):
        self.users = users
        self.index = 0

    def __getitem__(self, item):
        return self.users[item]


if __name__ == "__main__":
    c = Company(["小明", "小红", "小刚"])
    my_itor = iter(c)
    while True:
        try:
            item = next(my_itor)
            print(item)
        except StopIteration:
            pass

生成器

示例

只要方法中有yield,就会被解析为生成器

import dis
def gen_func():
    name = "小红"
    yield name
    name = "小明"
    yield name
    name = "小刚"


if __name__ == "__main__":
    g = gen_func()
    dis.dis(g)
    print("-----------------")
    print(g.gi_frame.f_lasti)
    print(g.gi_frame.f_locals)
    print("-----------------")
    print(next(g))
    print(g.gi_frame.f_lasti)
    print(g.gi_frame.f_locals)
    print("-----------------")
    print(next(g))

其中

g = gen_func()获取生成器对象 dis.dis(g)能查看生成器对象的字节码执行过程 g.gi_frame.f_lasti能查看字节码执行的行号 g.gi_frame.f_locals能查看当时的环境变量

结果

  3           0 LOAD_CONST               1 ('小红')
              2 STORE_FAST               0 (name)

  4           4 LOAD_FAST                0 (name)
              6 YIELD_VALUE
              8 POP_TOP

  5          10 LOAD_CONST               2 ('小明')
             12 STORE_FAST               0 (name)

  6          14 LOAD_FAST                0 (name)
             16 YIELD_VALUE
             18 POP_TOP

  7          20 LOAD_CONST               3 ('小刚')
             22 STORE_FAST               0 (name)
             24 LOAD_CONST               0 (None)
             26 RETURN_VALUE
-----------------
-1
{}
-----------------
小红
6
{'name': '小红'}
-----------------
小明

我们可以用for来遍历生成器的结果

def gen_func():
    name = "小红"
    yield name
    name = "小明"
    yield name
    name = "小刚"
    return name


if __name__ == "__main__":
    g = gen_func()
    for item in g:
        print(item)

结果

小红
小明

可以看出我们只能接收yield返回的值

读取文件

读取多行文件

aaaaaa
bbb
ccc
dd

读取

with open("input.txt") as f:
    for line in f.readlines():
        print("line:" + line)

读取单行大文件

假如文件只有一行,并且文件较大,有固定的分隔符

aaaaaa[|]bbb[|]ccc[|]dd

读取代码

def myreadlines(f, separator):
    buf = ""
    while True:
        while separator in buf:
            pos = buf.index(separator)
            yield buf[:pos]
            buf = buf[pos + len(separator):]
        chunk = f.read(4096)
        if not chunk:
            yield buf
            break
        buf += chunk


with open("input.txt") as f:
    for line in myreadlines(f, "[|]"):
        print("line:" + line)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 迭代器
  • 生成器
    • 示例
      • 读取文件
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档