详解Python之可迭代对象,迭代器和生成器

目录
  • 一、概念描述
  • 二、序列的可迭代性
  • 三、经典的迭代器模式
  • 四、生成器也是迭代器
  • 五、实现惰性迭代器
  • 六、使用生成器表达式简化惰性迭代器
  • 总结

一、概念描述

可迭代对象就是可以迭代的对象,我们可以通过内置的iter函数获取其迭代器,可迭代对象内部需要实现__iter__函数来返回其关联的迭代器;

迭代器是负责具体数据的逐个遍历的,其通过实现__next__函数得以逐个的访问关联的数据元素;同时通过实现__iter__来实现对可迭代对象的兼容;

生成器是一种迭代器模式,其实现了数据的惰性生成,即只有使用的时候才会生成对应的元素;

二、序列的可迭代性

python内置的序列可以通过for进行迭代,解释器会调用iter函数获取序列的迭代器,由于iter函数兼容序列实现的__getitem__,会自动创建一个迭代器;

迭代器的

import re
from dis import dis
class WordAnalyzer:
    reg_word = re.compile('\w+')
    def __init__(self, text):
        self.words = self.__class__.reg_word.findall(text)
    def __getitem__(self, index):
        return self.words[index]
def iter_word_analyzer():
    wa = WordAnalyzer('this is mango word analyzer')
    print('start for wa')
    for w in wa:
        print(w)
    print('start while wa_iter')
    wa_iter = iter(wa)
    while True:
        try:
            print(next(wa_iter))
        except StopIteration as e:
            break;
iter_word_analyzer()
dis(iter_word_analyzer)
# start for wa
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# this
# is
# mango
# word
# analyzer
#  15           0 LOAD_GLOBAL              0 (WordAnalyzer)
#               2 LOAD_CONST               1 ('this is mango word analyzer')
#               4 CALL_FUNCTION            1
#               6 STORE_FAST               0 (wa)
#
#  16           8 LOAD_GLOBAL              1 (print)
#              10 LOAD_CONST               2 ('start for wa')
#              12 CALL_FUNCTION            1
#              14 POP_TOP
#
#  17          16 LOAD_FAST                0 (wa)
#              18 GET_ITER
#         >>   20 FOR_ITER                12 (to 34)
#              22 STORE_FAST               1 (w)
#
#  18          24 LOAD_GLOBAL              1 (print)
#              26 LOAD_FAST                1 (w)
#              28 CALL_FUNCTION            1
#              30 POP_TOP
#              32 JUMP_ABSOLUTE           20
#
#  20     >>   34 LOAD_GLOBAL              1 (print)
#              36 LOAD_CONST               3 ('start while wa_iter')
#              38 CALL_FUNCTION            1
#              40 POP_TOP
#
#  21          42 LOAD_GLOBAL              2 (iter)
#              44 LOAD_FAST                0 (wa)
#              46 CALL_FUNCTION            1
#              48 STORE_FAST               2 (wa_iter)
#
#  23     >>   50 SETUP_FINALLY           16 (to 68)
#
#  24          52 LOAD_GLOBAL              1 (print)
#              54 LOAD_GLOBAL              3 (next)
#              56 LOAD_FAST                2 (wa_iter)
#              58 CALL_FUNCTION            1
#              60 CALL_FUNCTION            1
#              62 POP_TOP
#              64 POP_BLOCK
#              66 JUMP_ABSOLUTE           50
#
#  25     >>   68 DUP_TOP
#              70 LOAD_GLOBAL              4 (StopIteration)
#              72 JUMP_IF_NOT_EXC_MATCH   114
#              74 POP_TOP
#              76 STORE_FAST               3 (e)
#              78 POP_TOP
#              80 SETUP_FINALLY           24 (to 106)
#
#  26          82 POP_BLOCK
#              84 POP_EXCEPT
#              86 LOAD_CONST               0 (None)
#              88 STORE_FAST               3 (e)
#              90 DELETE_FAST              3 (e)
#              92 JUMP_ABSOLUTE          118
#              94 POP_BLOCK
#              96 POP_EXCEPT
#              98 LOAD_CONST               0 (None)
#             100 STORE_FAST               3 (e)
#             102 DELETE_FAST              3 (e)
#             104 JUMP_ABSOLUTE           50
#         >>  106 LOAD_CONST               0 (None)
#             108 STORE_FAST               3 (e)
#             110 DELETE_FAST              3 (e)
#             112 RERAISE
#         >>  114 RERAISE
#             116 JUMP_ABSOLUTE           50
#         >>  118 LOAD_CONST               0 (None)
#             120 RETURN_VALUE

三、经典的迭代器模式

标准的迭代器需要实现两个接口方法,一个可以获取下一个元素的__next__方法和直接返回self的__iter__方法;

迭代器迭代完所有的元素的时候会抛出StopIteration异常,但是python内置的for、列表推到、元组拆包等会自动处理这个异常;

实现__iter__主要为了方便使用迭代器,这样就可以最大限度的方便使用迭代器;

迭代器只能迭代一次,如果需要再次迭代就需要再次调用iter方法获取新的迭代器,这就要求每个迭代器维护自己的内部状态,即一个对象不能既是可迭代对象同时也是迭代器;

从经典的面向对象设计模式来看,可迭代对象可以随时生成自己关联的迭代器,而迭代器负责具体的元素的迭代处理;

import re
from dis import dis
class WordAnalyzer:
    reg_word = re.compile('\w+')
    def __init__(self, text):
        self.words = self.__class__.reg_word.findall(text)
    def __iter__(self):
        return WordAnalyzerIterator(self.words)
class WordAnalyzerIterator:
    def __init__(self, words):
        self.words = words
        self.index = 0
    def __iter__(self):
        return self;
    def __next__(self):
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration()
        self.index +=1
        return word
def iter_word_analyzer():
    wa = WordAnalyzer('this is mango word analyzer')
    print('start for wa')
    for w in wa:
        print(w)
    print('start while wa_iter')
    wa_iter = iter(wa)
    while True:
        try:
            print(next(wa_iter))
        except StopIteration as e:
            break;
iter_word_analyzer()
# start for wa
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# this
# is
# mango
# word
# analyzer

四、生成器也是迭代器

生成器是调用生成器函数生成的,生成器函数是含有yield的工厂函数;

生成器本身就是迭代器,其支持使用next函数遍历生成器,同时遍历完也会抛出StopIteration异常;

生成器执行的时候会在yield语句的地方暂停,并返回yield右边的表达式的值;

def gen_func():
    print('first yield')
    yield 'first'
    print('second yield')
    yield 'second'
print(gen_func)
g = gen_func()
print(g)
for val in g:
    print(val)
g = gen_func()
print(next(g))
print(next(g))
print(next(g))
# <function gen_func at 0x7f1198175040>
# <generator object gen_func at 0x7f1197fb6cf0>
# first yield
# first
# second yield
# second
# first yield
# first
# second yield
# second
# StopIteration

我们可以将__iter__作为生成器函数

import re
from dis import dis
class WordAnalyzer:
    reg_word = re.compile('\w+')
    def __init__(self, text):
        self.words = self.__class__.reg_word.findall(text)
    def __iter__(self):
        for word in self.words:
            yield word
def iter_word_analyzer():
    wa = WordAnalyzer('this is mango word analyzer')
    print('start for wa')
    for w in wa:
        print(w)
    print('start while wa_iter')
    wa_iter = iter(wa)
    while True:
        try:
            print(next(wa_iter))
        except StopIteration as e:
            break;
iter_word_analyzer()
# start for wa
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# this
# is
# mango
# word
# analyzer

五、实现惰性迭代器

迭代器的一大亮点就是通过__next__来实现逐个元素的遍历,这个大数据容器的遍历带来了可能性;

我们以前的实现在初始化的时候,直接调用re.findall得到了所有的序列元素,并不是一个很好的实现;我们可以通过re.finditer来在遍历的时候得到数据;

import re
from dis import dis
class WordAnalyzer:
    reg_word = re.compile('\w+')
    def __init__(self, text):
        # self.words = self.__class__.reg_word.findall(text)
        self.text = text
    def __iter__(self):
        g = self.__class__.reg_word.finditer(self.text)
        print(g)
        for match in g:
            yield match.group()
def iter_word_analyzer():
    wa = WordAnalyzer('this is mango word analyzer')
    print('start for wa')
    for w in wa:
        print(w)
    print('start while wa_iter')
    wa_iter = iter(wa)
    wa_iter1= iter(wa)
    while True:
        try:
            print(next(wa_iter))
        except StopIteration as e:
            break;
iter_word_analyzer()
# start for wa
# <callable_iterator object at 0x7feed103e040>
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# <callable_iterator object at 0x7feed103e040>
# this
# is
# mango
# word
# analyzer

六、使用生成器表达式简化惰性迭代器

生成器表达式是生成器的声明性定义,与列表推到的语法类似,只是生成元素是惰性的;

def gen_func():
    print('first yield')
    yield 'first'
    print('second yield')
    yield 'second'
l = [x for x in gen_func()]
for x in l:
    print(x)
print()
ge = (x for x in gen_func())
print(ge)
for x in ge:
    print(x)
# first yield
# second yield
# first
# second
#
# <generator object <genexpr> at 0x7f78ff5dfd60>
# first yield
# first
# second yield
# second

使用生成器表达式实现word analyzer

import re
from dis import dis
class WordAnalyzer:
    reg_word = re.compile('\w+')
    def __init__(self, text):
        # self.words = self.__class__.reg_word.findall(text)
        self.text = text
    def __iter__(self):
        # g = self.__class__.reg_word.finditer(self.text)
        # print(g)
        # for match in g:
        #     yield match.group()
        ge = (match.group() for match in self.__class__.reg_word.finditer(self.text))
        print(ge)
        return ge
def iter_word_analyzer():
    wa = WordAnalyzer('this is mango word analyzer')
    print('start for wa')
    for w in wa:
        print(w)
    print('start while wa_iter')
    wa_iter = iter(wa)
    while True:
        try:
            print(next(wa_iter))
        except StopIteration as e:
            break;
iter_word_analyzer()
# start for wa
# <generator object WordAnalyzer.__iter__.<locals>.<genexpr> at 0x7f4178189200>
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# <generator object WordAnalyzer.__iter__.<locals>.<genexpr> at 0x7f4178189200>
# this
# is
# mango
# word
# analyzer
 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • python学习之可迭代对象、迭代器、生成器

    Iterable – 可迭代对象 能够逐一返回其成员项的对象. 可迭代对象的例子包括所有序列类型 (例如 list, str 和 tuple) 以及某些非序列类型例如 dict, 文件对象以及定义了__iter__()方法或是实现了序列语义的__getitem__() 方法的任意自定义类对象. 可迭代对象可用于 for 循环以及许多其他需要一个序列的地方(zip().map() -).当一个可迭代对象作为参数传给内置函数 iter() 时,它会返回该对象的迭代器.这种迭代器适用于对值集合的一次性

  • 一篇文章弄懂Python中的可迭代对象、迭代器和生成器

    我们都知道,序列可以迭代.但是,你知道为什么吗? 本文来探讨一下迭代背后的原理. 序列可以迭代的原因:iter 函数.解释器需要迭代对象 x 时,会自动调用 iter(x).内置的 iter 函数有以下作用: (1) 检查对象是否实现了 iter 方法,如果实现了就调用它,获取一个迭代器. (2) 如果没有实现 iter 方法,但是实现了 getitem 方法,而且其参数是从零开始的索引,Python 会创建一个迭代器,尝试按顺序(从索引 0 开始)获取元素. (3) 如果前面两步都失败,Pyt

  • 稳扎稳打学Python之容器 可迭代对象 迭代器 生成器专题讲解

    目录 一.容器 1.什么是容器? 二.可迭代对象 1.什么是可迭代对象? 三.迭代器 四.序列 五.列表推导式 六.生成器 1.生成器的第一种创建方法:生成器表达式 2.生成器的第二种创建方法:yield 七.小结 今天就来给大家讲讲Python中的容器.可迭代对象.迭代器和生成器这些难理解的概念,让你的Python基础更上一层楼! 一.容器 1.什么是容器? 在Python中,容器是把多种元素组织在一起的数据结构,容器中的元素就可以逐个迭代获取.说白了,它的作用就像它的名字一样:用来存放东西(

  • 浅谈Python中的可迭代对象、迭代器、For循环工作机制、生成器

    1.iterable iterator区别 要了解两者区别,先要了解一下迭代器协议: 迭代器协议是指:对象需要提供__next__()方法,它返回迭代中的元素,在没有更多元素后,抛出StopIteration异常,终止迭代. 可迭代对象就是:实现了迭代器协议的对象. 协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(如for循环,sum,min,max函数等)通过迭代器协议访问对象,因此,for循环并不需要知道对象具体是什么,只需要知道对象能够实现迭代器协议即可. 迭代器(ite

  • python生成器,可迭代对象,迭代器区别和联系

    生成器,可迭代对象,迭代器之间究竟是什么关系? 用一幅图来概括: 1.生成器 定义生成器 方式一: //区别于列表生成式 gen = [x*x for x in range(5)] gen = (x*x for x in range(5)) print(gen) //Out:<generator object <genexpr> at 0x00000258DC5CD8E0> 方式二: def fib(): prev, curr = 0, 1 while True: yield cu

  • 详解Python之可迭代对象,迭代器和生成器

    目录 一.概念描述 二.序列的可迭代性 三.经典的迭代器模式 四.生成器也是迭代器 五.实现惰性迭代器 六.使用生成器表达式简化惰性迭代器 总结 一.概念描述 可迭代对象就是可以迭代的对象,我们可以通过内置的iter函数获取其迭代器,可迭代对象内部需要实现__iter__函数来返回其关联的迭代器; 迭代器是负责具体数据的逐个遍历的,其通过实现__next__函数得以逐个的访问关联的数据元素;同时通过实现__iter__来实现对可迭代对象的兼容; 生成器是一种迭代器模式,其实现了数据的惰性生成,即

  • Python中for循环可迭代对象迭代器及生成器源码学习

    目录 问题: 1. 迭代 1.1 可迭代对象Iterable 1.2 迭代器Iterator 1.3 for循环 1.3.1 iter()方法和next()方法 1.3.2 iter()和__iter__() 1.3.3 next()和__next__() 1.3.4 自定义类实现__iter__()和__next__() 1.3.5 探究for循环 2 生成器 2.1 获取生成器 2.2 next(生成器) 2.3 生成器和迭代器 2.4 生成器解析式 问题: 之前在学习list和dict相关

  • 详解python 拆包可迭代数据如tuple, list

    拆包是指将一个结构中的数据拆分为多个单独变量中. 以元组为例: >>> a = ('windows', 10, 25.1, (2017, 12, 29)) 假设数据的意思是购买windows 10 份, 每份价值25.1刀.数据获取时间是2017年12月29日. 我们需要获取该数据中每份的价格: >>> a[2] 也可以使用拆包的方法: >>>os_type, number, price, dat = a >>>price 注意的问题

  • 详解Python中的内建函数,可迭代对象,迭代器

    Python中的内建函数和可迭代对象,迭代器 求值标识 id() #标识id 返回对象的唯一标识,CPython返回内存地址 hash() #哈希, 返回对象的哈希值 len(s) -->返回一个集合类型的元素个数 range(start,stop[,step]) -->返回一个从start开始到stop结束,步长为step的可迭代对象.step默认为1 类型判断 type() #返回对象的类型 isinstance(obj,class_or_tuple) ->True|False #判

  • 详解Python中for循环的定义迭代方法

    目录 Python的 for 循环 遍历字典 range()功能 break语句 和continue语句 else语句 Python的 for 循环 Python 是基于集合的迭代. for <var> in <iterable>: # <iterable>是对象的集合--例如,列表或元组. <statement(s)> # 循环体 a = ['曹操', '孫権', '劉備'] for i in a: print(i) 输出: 曹操孫権劉備 可迭代对象 ,可

  • 详解Python中迭代器和生成器的原理与使用

    目录 1.可迭代对象.迭代器 1.1概念简介 1.2可迭代对象 1.3迭代器 1.4区分可迭代对象和迭代器 1.5可迭代对象和迭代器的关系 1.6可迭代对象和迭代器的工作机制 1.7自己动手创建可迭代对象和迭代器 1.8迭代器的优势 1.9迭代器的缺点和误区 1.10python自带的迭代器工具itertools 2.生成器 2.1生成器的创建方法 2.2生成器方法 2.3生成器的优势 2.4生成器应用场景 3.生成器节省内存.迭代器不节省内存 3.1可迭代对象 3.2迭代器 3.3生成器 3.

  • 以SortedList为例详解Python的defaultdict对象使用自定义类型的方法

    目录 写在前面 第一种方法: 封装成函数 第二种方法: 类封装 写在前面 最近写周赛题, 逃不开的一种题型是设计数据结构, 也就是第三题, 做这种题需要的就是对语言中的容器以及常用排序查找算法的掌握, 而我只熟悉了最基本的一些方法, 做起这些题来总是超时… 为了搞定这些题, 我决定学习一下大佬们的做法, 特别是优先队列的方法维护有序容器以及有序列表等容器, 这些都在Python中封装好了, 用起来很是方便, 但是采用defaultdict的时候, 其缺省数据类型常常需要与题目给出的特定结构匹配,

  • 详解 Python 与文件对象共事的实例

    详解 Python 与文件对象共事的实例 Python 有一个内置函数,open,用来打开在磁盘上的文件.open 返回一个文件对象,它拥有一些方法和属性,可以得到被打开文件的信息,以及对被打开文件进行操作. >>> f = open("/music/_singles/kairo.mp3", "rb") (1) >>> f (2) <open file '/music/_singles/kairo.mp3', mode 'r

  • Python通过for循环理解迭代器和生成器实例详解

    本文实例讲述了Python通过for循环理解迭代器和生成器.分享给大家供大家参考,具体如下: 迭代器 可迭代对象 通过 for-in- 循环依次拿到数据进行使用的过程称为遍历,也叫迭代.我们把可以通过 for-in- 语句迭代读取数据的对象称之为可迭代对象. - 通过 isinstance()可以判断一个对象是否可以迭代 # 判断列表 print(isinstance([], Iterable) 打印结果为 True 即为可迭代对象. - 自定义一个能容纳数据的类,测试该类的可迭代性 impor

  • python 协程中的迭代器,生成器原理及应用实例详解

    本文实例讲述了python 协程中的迭代器,生成器原理及应用.分享给大家供大家参考,具体如下: 1.迭代器理解 迭代器: 迭代器是访问可迭代对象的工具 迭代器是指用iter(obj)函数返回的对象(实例) 迭代器是指用next(it)函数获取可迭代对象的数据 迭代器函数(iter和next) iter(iterable)从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象 next(iterator) 从迭代器iterator中获取下一了记录,如果无法获取下一条记录,则触发

随机推荐