第八章:Python高级编程-迭代器和生成器
第八章:Python高级编程-迭代器和生成器
Python3高级核心技术97讲 笔记
目录
- 第八章:Python高级编程-迭代器和生成器
- 8.1 Python中的迭代协议
- 8.2 什么是迭代器和可迭代对象
- 8.3 生成器函数的使用
- 8.4 Python是如何实现生成器的?
- 8.5 生成器在UserList中的应用
- 8.6 生成器如何读取大文件
 
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)


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)

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号