zoukankan      html  css  js  c++  java
  • 第八章:Python高级编程-迭代器和生成器

    第八章:Python高级编程-迭代器和生成器

    Python3高级核心技术97讲 笔记

    8.1 Python中的迭代协议

    """
    什么是迭代协议
    迭代器是什么? 迭代器是访问集合内元素的一种方式, 一般用来遍历数据
    迭代器和以下标的访问方式不一样, 迭代器是不能返回的, 迭代器提供了一种惰性方式数据的方式
    [] list , __iter__ __next__
    """
    class Iterable(metaclass=ABCMeta):
    
        __slots__ = ()
    
        @abstractmethod
        def __iter__(self):
            while False:
                yield None
    
        @classmethod
        def __subclasshook__(cls, C):
            if cls is Iterable:
                return _check_methods(C, "__iter__")
            return NotImplemented
    
    
    class Iterator(Iterable):
    
        __slots__ = ()
    
        @abstractmethod
        def __next__(self):
            'Return the next item from the iterator. When exhausted, raise StopIteration'
            raise StopIteration
    
        def __iter__(self):
            return self
    
        @classmethod
        def __subclasshook__(cls, C):
            if cls is Iterator:
                return _check_methods(C, '__iter__', '__next__')
            return NotImplemented
        
    

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

    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:  # 执行了iter(company)
            print (item)
    

    8.3 生成器函数的使用

    # 生成器函数,函数里只要有yield关键字
    # 惰性求值,延迟求值提供了可能
    
    
    def gen_func():  # 返回的是一个生成器对象,在Python编译字节码是产生
        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
    
    

    8.4 Python是如何实现生成器的?

    #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 = "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)
    
    
    生成器 生成器2

    8.5 生成器在UserList中的应用

    class company:
        def __getitem__(self, item):
            pass
    
    from collections import UserList  # 不要用继承list,因为是c写的
    
    def __iter__(self):
        i = 0
        try:
            while True:
                v = self[i]
                yield v
                i += 1
    	except IndexError:
            return
    

    8.6 生成器如何读取大文件

    #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)
    
    
    
  • 相关阅读:
    python 不可变类型
    python 不定长参数
    Codeforces Round #749
    [提高组集训2021] Round1
    AtCoder Regular Contest 128
    [提高组互测] Day6
    [提高组互测] Day5
    [提高组互测] Day1
    [提高组互测] Day2
    [提高组集训2021] 一拳超人
  • 原文地址:https://www.cnblogs.com/xunjishu/p/12858616.html
Copyright © 2011-2022 走看看