IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python可迭代对象、迭代器和生成器 -> 正文阅读

[Python知识库]python可迭代对象、迭代器和生成器

python可迭代对象、迭代器和生成器

一、简介

1、关于迭代器和生成器

关于python的迭代器和生成器这两个概念,大多数程序员都认为其在功能上是类似的,在python官方文档中也有时认为迭代器就是生成器,其实这两种还是有一定的区别。

使用内置函数iter()可以生成迭代器,使用内置函数next()可以获得迭代器中的值。

第一点,从概念上
在典型的迭代器设计模式中,迭代器用于遍历集合,从中产出元素,迭代器不能修改数据源中的值,只能原封不动地产出,而生成器可能无需遍历就能生成值。

第二点,从接口方面
python的迭代器协议定义了两个方法__iter____next__,生成器实现了这两个方法,因此从这方面来看,所有的生成器都是迭代器。

第三点、从实现方面
生成器这种python语言结构可以使用两种方式编写:1、含有yield关键字的函数,称之为生成器函数。2、使用生成器表达式。

2、关于可迭代对象

为什么是可迭代的?

在介绍可迭代对象之前,我们先了解一下python中序列可迭代的原因,序列之所以可以迭代是因为iter()内置函数,iter()内置函数有以下作用:

(1) 检查对象是否实现了__iter__方法,如果实现了就调用它,获取一个迭代器

(2) 如果没有实现__iter__方法,但是实现了__getitem__方法,python会创建一个迭代器,尝试按照顺序(从索引0)开始获取元素。

(3) 如果上述尝试均失败,python会抛出TypeError异常

什么是可迭代对象?

按照上面python序列可迭代的原因来看,Python中任意的对象,只要它定义了可以返回一个迭代器的 __iter__ 方法,或者定义了可以支持下标索引的 __getitem__ 方法,那么它就是一个可迭代对象。简单说,可迭代对象就是能提供迭代器的任意对象。

二、可迭代对象

可迭代对象可以使用内置iter()函数获取迭代器的对象,如果对象实现了能返回迭代器的__iter__方法,那么对象就是可以迭代的。序列都可以迭代;实现了__getitem__方法,而且其参数是从零开始的索引,这种对象也可以迭代。

按照上面我们对可迭代对象的定义,我们进行如下代码实验

import re
import reprlib

RE_WORD = re.compile('\w+')

class Sentence(object):

    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)  # re.findall函数返回一个字符串列表,得到匹配的单词
    
    # 我们只实现了__getitem__方法
    def __getitem__(self, index):
        return self.words[index]
    
    def __repr__(self):
        return 'Sentence(%s)' % reprlib.repr(self.text)
    
s = Sentence('My favorite language is python !')
print(s)
# 我们迭代打印s中的值,打印成功则Sentence类是可以迭代的
for word in s: print(word)
Sentence('My favorite ...e is python !')
My
favorite
language
is
python

在上述代码实验中,我们并没有重载__itet__方法,而是重载了__getitem__方法,我们自定义的Sentence类仍然是可以迭代的,说明我们之前对可迭代对象的定义正确。

我们来验证是否能够使用iter()内置函数来直接获取对象的迭代器,

s1 = Sentence('Hi Python')
it = iter(s1)  # 获取序列的迭代器对象
print(next(it))
print(next(it))
Hi
Python

结果表明,我能确实能够获得序列对象的迭代器。

三、迭代器

标准的迭代器需要实现的方法:

(1) __next__ 返回下一个可用的元素,如果没有元素,抛出StopIteration异常。

(2) __iter__ 返回self,以便在应该使用可迭代对象的地方使用迭代器,例如for循环中。
在这里插入图片描述

现在我们按照迭代的标准写法,来改写前一个列子的代码。

import re
import reprlib

RE_WORD = re.compile('\w+')

class Sentence(object):  # 可迭代对象实现__iter__

    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __repr__(self):
        return "Sentence(%s)" % reprlib.repr(self.text)
    
    def __iter__(self):
        return SentenceIterator(self.words)
    
class SentenceIterator(object):  # 迭代器实现__next__和__iter__

    def __init__(self, words):
        self.words = words
        self.index = 0
    
    def __next__(self):
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1
        return word
    
    def __iter__(self):
        return self

s1 = Sentence('My favorite language is Python!')
print(s1)
print('================================')

for word in s1: print(word)

it = iter(s1)
print('================================')
print(next(it))
print(next(it))

Sentence('My favorite ...ge is Python!')
================================
My
favorite
language
is
Python
================================
My
favorite

在构建迭代器对象和迭代器时经常会出现错误,原因是混淆了两者,要知道,可迭代的对象有一个__iter__方法,每次都实例化一个新的迭代器;而迭代器要实现__next__方法,返回单个元素,此外还要实现__iter__方法,返回迭代器本身。

小结:
可迭代的对象一定不能是自身的迭代器,也就是说,可迭代的对象必须实现__iter__方法,但是不能实现__next__方法。
另一方面,迭代器应该可以一直迭代,迭代器的__iter__方法应该返回自身。

四、生成器与生成器函数

1、生成器函数

先介绍什么是生成器函数,在普通函数定义中,不需要return,而是采用yield关键字来“产生”值,该函数就是生成器函数。调用生成器函数时,会返回一个生成器对象,也就是说生成器函数是生成器工厂。

定义一个简单的生成器函数:

def gen_123():
    for i in [1,2,3]:
        yield i

it = gen_123()
print(next(it))
print(next(it))
print(next(it))
1
2
3

上述代码中,为了实现相同的功能,符合python编程风格的做法是,用生成器函数来代替SentenceIterator类

import re
import reprlib

RE_WORD = re.compile('\w+')

class Sentence(object):  # 可迭代对象实现__iter__

    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __repr__(self):
        return "Sentence(%s)" % reprlib.repr(self.text)
    
    def __iter__(self): # 替换成生成器函数
        for word in self.words:
            yield word

s2 = Sentence('My favorite language is Pythooooon!')
print(s2)
print('================================')

for word in s2: print(word)
print('================================')

it = iter(s2)
print(next(it))
print(next(it))
Sentence('My favorite ...s Pythooooon!')
================================
My
favorite
language
is
Pythooooon
================================
My
favorite

注意我们在此,并没有定义迭代器类,而是使用生成器函数来代替迭代器的类,更加pythonic

2、生成器表达式

生成器表达式,和列表生成式字典生成式等类似,只不过将[ ]替换成( )

it = (x for x in [1,2,3,4])
print(type(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
<class 'generator'>
1
2
3
4

五、Reference

https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128
https://www.runoob.com/python3/python3-iterator-generator.html
https://py.eastlakeside.cn/book/DataStructures/generators.html
《FluentPython》

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:33:48  更:2022-02-01 20:33:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 1:30:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码