再谈迭代器,生成器,yield,及和类的使用

来源:互联网 发布:灭绝师太 武功 知乎 编辑:程序博客网 时间:2024/06/18 12:32

最近写项目时,遇到类嵌套和yield的混合使用,觉得比较典型,正好借此加深对迭代器和生成器的理解。

代码

代码抽象如下:

from types import FunctionTypeclass RowItems(object):    def __init__(self,option,x1,x2,x3):        self.option = option        self.x1 = x1        self.x2 = x2        self.x3 = x3    def __iter__(self):        yield 1        yield 11        yield 111        yield 1111        yield 11111        yield 111111        yield 1111111class Option(object):    def __init__(self,name_or_func,status):        self.name_or_func = name_or_func        self.status = status    def is_func(self):        if isinstance(self.name_or_func,FunctionType):            return Truedef func(configs):    for option in configs:        if option.is_func():            data_list = None        else:            data_list = RowItems(option,11,22,33)        yield data_listlist_filter_config = [    Option('name',True),    Option('email',True),]result = func(list_filter_config)for v in result:    for j in v:        print(j)

打印结果如下:

11111111111111111111111111111111111111111111111111111111


知识准备:

关于迭代器和生成器的基本知识,可以参考 http://blog.csdn.net/ayhan_huang/article/details/73374894

我们知道,可迭代对象都具有__iter__方法,因此只要在类中定义该方法,那么其实例化对象就是可迭代对象,就可以被for循环,比如:

class Foo(object):    def __iter__(self):        return iter([1,2,3])obj = Foo()for i in obj:    print(i)""" 打印结果123"""


而如果一个函数中有yield,那么执行函数就会拿到一个生成器(生成器就是迭代器)。

流程分析:

下面我们具体看一下本文开头给出的那段代码的执行流程

  1. list_filter_config 中拿到两个实例化对象,假设为: A & B
  2. result = func(list_filter_config),未执行func具逻辑,直接拿到一个生成器对象,假设为F_gen
  3. for v in result: 执行生成器,F_gen
  4. 执行func :
    1. 循环list_filter_config第一个元素 A
    2. 实例化RowItems对象,得到可迭代对象,假设为:A_iter
    3. func:yield A_iter 返回 A_iter
  5. 回到for v in result: A_iter, F_gen
    1. for j in v: 迭代A_iter:每打印一行,回到for j in v,触发A_iter继续迭代
    2. 迭代A_iter 完成,打印出第一个金字塔
  6. 回到for v in result: F_gen
  7. 执行func :
    1. 循环list_filter_config第二个元素 B
    2. 实例化RowItems对象,得到可迭代对象,假设为:B_iter
    3. func:yield B_iter 返回 B_iter
  8. 回到for v in result: B_iter
    1. for j in v: 迭代B_iter:每打印一行,回到for j in v,触发B_iter继续迭代
    2. 迭代B_iter完成,打印出第二个金字塔
原创粉丝点击