python高级编程------可迭代对象,迭代器

一。迭代 协议,迭代器,可迭代对象   概念

#什么是迭代协议    (可迭代类型Iterable,iterator )
#迭代器是什么? 迭代器是访问集合内元素的一种方式, 一般用来遍历数据
#迭代器和以下标的访问方式不一样, 迭代器是不能返回(反向)的, 迭代器提供了一种惰性方式数据的方式
#[] list , __iter__(迭代协议)
#只要实现__iter__方法就是可迭代对象,但不是迭代器
#Iterator继承Iterable,实现了__iter__,和 __next__(是一个@abstractmethod)
from collections.abc import Iterable, Iterator
a = [1,2]
iter_rator = iter(a)
print (isinstance(a, Iterable))  #判断是否是可迭代的   True
print (isinstance(iter_rator, Iterator)) #判断是否是迭代器  True
print (isinstance(a, Iterator)) #判断是否是迭代器   False


二。自定义迭代器

在实现迭代器的时候,可以继承自Iterator,iterator内部实现了__iter__,我们只需要重写__next__方法就行

当然可迭代对象内部也可以实现__next__,但是不符合设计模式

新学知识点:对于要处理的数据,我们可以通过实现迭代协议对齐进行优化处理

如下面的MyIterator

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:#for内部自动处理了stopIteration
        print (item)

三。生成器

#生成器函数,函数里只要有yield关键字
#生成器对象也是实现了迭代器协议的,可以使用for循环
#函数只能返回一个,而生成器也以一直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

四。生成器原理

#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, 又会创建一个栈帧
所有的栈帧都是分配在堆内存上,这就决定了栈帧可以独立于调用者存在

与静态语言不同,静态语言的函数调用是在栈上,函数执行完毕站就会销毁
而python的函数的执行,是将栈都分配在退内存上,
"""
# 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)

class company:
    def __getitem__(self, item):#通过索引的形式访问
        pass

from collections import UserList

 

对生成器的 进一步封装,f_lasti指向上一次代码执行的位置,f_locals是变量的

生成器对象是分配在退内存中的,可以独立于调用者

 

python高级编程------可迭代对象,迭代器

 

python高级编程------可迭代对象,迭代器

list的内部实现的遍历原理

python高级编程------可迭代对象,迭代器