第七课 python迭代器生成器

第七课 python迭代器生成器

tags:

  • Python
  • 慕课网

categories:

  • 迭代器
  • 生成器

第一节 python中的迭代协议

  1. 迭代器是什么? 迭代器是访问集合内元素的一种方式, 一般用来遍历数据
  2. 迭代器和以下标的访问方式不一样, 迭代器是不能返回的, 迭代器提供了一种惰性方式数据的方式
# [] list , __iter__是我们的迭代协议
# 查看源码 发现Iterable继承了Iterator的抽象基类
from collections.abc import Iterable, Iterator
a = [1, 2]
iter_rator = iter(a)
# Iterable可迭代只需要实现__iter__, Iterator迭代器除了实现__iter__还要实现__next__
print(isinstance(a, Iterable))
print(isinstance(a, Iterator))
print(isinstance(iter_rator, Iterator))

第二节 python迭代器和可迭代对象

  1. 定义__iter__时一定要返回Iterator,如果不是会报错
from collections.abc import Iterator


# __next__写在这 违背了迭代器设计模式的设计原则
class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list

    # 定义__iter__时一定要返回Iterator,如果不是会报错
    def __iter__(self):
        return MyIterator(self.employee)

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


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

    def __next__(self):
        # 真正返回迭代值的逻辑
        try:
            word = self.iter_list[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1
        return word

    # 这里继承了Iterator所以不用重写__iter__
    # def __iter__(self):
    #     return self


if __name__ == "__main__":
    company = Company(["tom", "bob", "jane"])
    my_itor = iter(company)
    # while True:
    #     try:
    #         print (next(my_itor))
    #     except StopIteration:
    #         pass
    # next(my_itor)
    for item in company:
        print(item)

第三节 python生成器

  1. 函数里只要有yield关键字就是我们的生成器函数
  2. 生成器对象, python编译字节码的时候就产生了
# 生成器函数,函数里只要有yield关键字
def gen_func():
    yield 1
    yield 2
    yield 3


def fib(index):
    if index <= 2:
        return 1
    else:
        return fib(index-1) + fib(index-2)


def fib2(index):
    re_list = []
    n, a, b = 0, 0, 1
    while n < index:
        re_list.append(b)
        a, b = b, a+b
        n += 1
    return re_list


# 使用生成器非常节省内存
def gen_fib(index):
    n, a, b = 0, 0, 1
    while n < index:
        yield b
        a, b = b, a+b
        n += 1


for data in gen_fib(10):
    print(data)
# print (gen_fib(10))
# 斐波拉契 0 1 1 2 3 5 8
# 惰性求值, 延迟求值提供了可能


def func():
    return 1


if __name__ == "__main__":
    # 生成器对象, python编译字节码的时候就产生了
    gen = gen_func()
    for value in gen:
        print(value)
    # re = func()
    # pass

第四节 python生成器原理

  1. 函数调用原理
    在这里插入图片描述

  2. 生成器对象内存,又加了一层PyGenObject
    在这里插入图片描述

# 1.python中函数的工作原理
"""

"""
import inspect
frame = None


def foo():
    bar()


def bar():
    global frame
    frame = inspect.currentframe()

# python.exe会用一个叫做PyEval_EvalFramEx(c函数)去执行foo函数, 首先会创建一个栈帧(stack frame)
"""
python一切皆对象,栈帧对象, 字节码对象
当foo调用子函数 bar, 又会创建一个栈帧
所有的栈帧都是分配在堆内存上,这就决定了栈帧可以独立于调用者存在
"""
# 查看字节码对象
# import dis
# print(dis.dis(foo))

foo()
# 可以找到frame的栈帧 也可以得到调用者的栈帧
print(frame.f_code.co_name)
caller_frame = frame.f_back
print(caller_frame.f_code.co_name)


# 生成器代码
def gen_func():
    yield 1
    name = "bobby"
    yield 2
    age = 30
    return "imooc"


import dis
gen = gen_func()
print(dis.dis(gen))
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)
next(gen)
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)
next(gen)
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)


class company:
    def __getitem__(self, item):
        pass

# UserList以python的方式解释List如何实现
# UserList可以用来继承 List因为是C写的 一些原生方法不好继承
from collections import UserList

第五节 生成器如何读取大文件

  1. 这里的文件是只有一行,一行有500G
  2. 用{|}作为行分割符
  3. 用生成器每次读取4096
# 500G, 特殊 只有一行 一行500G {|}这个是行分割符
def myreadlines(f, newline):
  buf = ""
  while True:
    while newline in buf:
      pos = buf.index(newline)
      yield buf[:pos]
      buf = buf[pos + len(newline):]
    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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值