首页 > 技术文章 > python高级(02)--生成器和迭代器

pankypan 2020-09-13 22:05 原文

python高级(02)--生成器和迭代器

python的迭代协议

# 什么是迭代协议
# 迭代器是什么? 迭代器是访问集合内元素的一种方式, 一般用来遍历数据
# 迭代器和以下标的访问方式不一样, 迭代器是不能返回的, 迭代器提供了一种惰性方式数据的方式
# [] list , __iter__


from collections.abc import Iterable, Iterator


a = [1, 2]
print(isinstance(a, Iterable))
print(isinstance(a, Iterator))
to_iterator = iter(a)
print(isinstance(to_iterator, Iterator))

什么是迭代器和可迭代对象

from collections.abc import Iterator


class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list

    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


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)

生成器的使用

# 生成器函数,函数里只要有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


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

    print(fib(10))
    print(fib2(10))
    g_fib = gen_fib(10)
    for i in g_fib:
        print(i)

生成器的原理

生成器

生成器2

# 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()
print(frame.f_code.co_name)
caller_frame = frame.f_back
print(caller_frame.f_code.co_name)


def gen_func():
    yield 1
    name = 'suki'
    sex = 'female'
    yield 2
    age = 30
    return 'snoopy'


import dis
gen = gen_func()
print(dis.dis(gen), '\n')

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)

通过UserList来看生成器的应用

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


from collections import UserList

生成器实现大文件读取

# 500G, 特殊 一行


def my_read_lines(f, new_line):
    buf = ""
    while True:
        while new_line in buf:
            pos = buf.index(new_line)
            yield buf[:pos]
            buf = buf[pos + len(new_line):]
        chunk = f.read(4096)

        if not chunk:
            yield buf
            break
        buf += chunk


with open('input.txt') as f:
    for line in my_read_lines(f, '{|}'):  # {|}为分隔符
        print(line)

推荐阅读