注册 登录
Python基础教程

第一章: 环境搭建,安装Python

第二章: 挑选一款趁手的IDE

第三章: 计算机基础知识

第四章: 命令行基础知识

第五章: 从全局把握Python

第六章: Python语言基础

第七章: Python流程控制

第八章: Python数据类型与运算

第九章: Python字符串类型

第十章: Python列表类型

第十一章: Python元组类型

第十二章: Python字典类型

第十三章: Python集合类型

第十四章: Python函数处理

第十五章: Python文件处理

第十六章: Python面向对象

第十七章: Python异常处理

第十八章: Python模块处理

第十九章: Python高级编程

第二十章: Python项目实战

首页 > Python基础教程 > 第十六章: Python面向对象 > 16.8节: 可迭代对象与迭代器

16.8节: 可迭代对象与迭代器

薯条老师 2022-11-28 10:55:56 26268 0

编辑 收藏

广州番禺Python, Java小班周末班培训

薯条老师在广州做Python和Java的小班培训,一个班最多10人,学员的平均就业薪资有11K不在广州的同学可以报名线上直播班,跟线下小班的同学们同步学习。培训的课程有Python爬虫,Python后端开发,Python办公自动化,Python大数据分析,Python量化投资,Python机器学习,Java中高级后端开发。授课详情请点击:http://chipscoco.com/?cate=6

16.8.1 什么是可迭代对象

在Python中,一切皆对象,只要在类中定义了__iter__方法,那么该类型就是可迭代的类型。定义__iter__方法时,通常只返回当前对象,表示当前对象是一个可迭代的对象。

代码实例:

# 定义Cat类
 
class Cat:
    # 定义类属性species, 表示猫所属的物种
    __species = "Cat" 
 
    @classmethod
    def catch_mice(cls):
        # 不会抓老鼠的猫不是好猫
        print("A cat that doesn't catch a mouse is not a good cat!")
 
 
    def __init__(self, name):
        self.__name = name
 
    # 在Cat中定义__iter__方法,表示该类型为可迭代类型
    def __iter__(self):
        # 在__iter__方法中,返回当前对象self
        # 表示当前对象是一个可迭代的对象
        return self
可迭代对象表示当前对象可以迭代,但是具体的迭代逻辑,还需要再定义__next__方法。在定义了__next__方法以后,该数据类型就变成了迭代器。

16.8.2 让可迭代对象变成迭代器

在类中定义了__iter__方法后,该类成为了可迭代类型。具体的迭代逻辑则由魔术方法__next__来负责。__iter__方法用来表明数据类型的性质:可迭代。至于如何迭代则与数据类型的具体实现有关,所以Python提供了__next__方法这个接口,供程序员来实现具体的迭代逻辑。

在通过__next__方法来定义具体的迭代逻辑时,必需遵循Python中的迭代器协议。同学们在理解迭代器协议时只需掌握以下两点:
(1) 在__next__方法中返回下一项
(2) 若无法再获取下一项,则必须抛出StopIteration的异常

在Python中,通过raise语句来抛出异常,关于异常,会在后续的教程中进行详细讲解。

代码实例:

# 定义Cat类
 
class Cat:
    # 定义类属性species, 表示猫所属的物种
    __species = "Cat" 
 
 
    @classmethod
    def catch_mice(cls):
        # 不会抓老鼠的猫不是好猫
        print("A cat that doesn't catch a mouse is not a good cat!")
 
    def __init__(self, name):
        self.__name = name
        self.__foods = []
        self.__index = 0
 
    def feed(food):
        self.__foods.append(food)
 
    # 在Cat中定义__iter__方法,表示该类型为可迭代类型
    def __iter__(self):
        # 在__iter__方法中,返回当前对象self
        return self
 

    # 在Cat中定义__next__方法,来定义具体的迭代逻辑
    # 定义__next__方法,必须遵循迭代器协议
 
    def __next__(self):
        """ 返回给猫喂过的食物 """
        if self.__index < len(self.__foods):
             food = self.__foods[self.__index]
             self.__index += 1
             return food
 
        # 如果索引超出有效范围,则重置为0
        self.__index = 0
        # 在__next__方法中抛出StopIteration的错误异常,系统会自动进行处理
        raise StopIteration
 
 
kitty = Cat("kitty")
kitty.feed("fish")
kitty.feed("bread")
 
# 定义了__next__方法以后,该对象即为迭代器,可以在for循环中进行遍历
 
for food in kitty:
    print(food)
 
"""
程序的输出为:
fish
bread
"""
在for循环中对迭代器对象进行遍历时,Python首先会检查该对象是否有定义__iter__方法,如果未进行定义,那么会抛出类型错误的异常信息,指示该对象不可迭代。若定义了__iter__方法,则再继续检查__next__方法。__iter__与__next__方法都定义时,再每次执行__next__方法来遍历对象中的元素。

16.8.3 全局的iter与next

在Python中提供了两个全局的迭代器方法,分别是iter与next。iter方法用来返回可迭代对象中的迭代器。next方法则用来遍历迭代器的值。到现在为止,学过的可迭代对象有:字符串,列表,元祖,字典,集合。现在同学们进入Python交互模式,在交互模式中来测试iter方法:

>>> cats = {"cat", "tiger", "lion"}
>>> cats_iter = iter(cats)
>>> type(cats_iter)
<class 'set_iterator'>

在交互模式中,定义了一个集合变量cats,然后通过iter方法来返回cats对象的迭代器。执行type时,其输出为set_iterator,表明该迭代器是集合对象中的迭代器。同学们同样可以在交互模式中测试其它的可迭代对象,例如测试字典时,type的的输出为<class 'dict_iterator'>。在交互模式中测试next方法,需要在next方法中传递一个迭代器:
>>> next(cats_iter)
'tiger'
>>> next(cats_iter)
'lion'
>>> next(cats_iter)
'cat'
>>> next(cats_iter)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration

通过上文的代码可知,获取迭代器中的值,需要不断地调用next方法,以这样的方式来使用迭代器可以实现惰性计算,即仅在需要的时候才执行next方法,迭代器内部负责维护元素遍历的状态信息。

在执行for循环来对可迭代对象进行遍历时,Python内部是通过iter(),next()的方式来逐一地访问对象中的元素。通过open函数返回的文件流对象,也是一种迭代器,相比于通过readlines方法一次性地将文件数据读取到内存,在for循环中通过迭代器来逐行地加载文件中的数据,大大地节约了内存的使用。

现在同学们参照以下步骤,一步步地进行今天的实战练习。

今天的实战练习为,用迭代器实现斐波纳契数列。在斐波纳契数列中,前面两项都为1,从第三项开始,每一项都等于前面两项之和。

(1) 在磁盘中编辑fib_numbers.py

用PyCharm打开D:\Python3-Learning\chapter16目录下的fib_numbers.py。并输入以下代码:

# __author__ = 薯条老师
# 微信公众号 =  薯条编程

class FNumbers:
    def __init__(self, end=100):
        self.__end, self.__a, self.__b = end, 0, 1
    def __iter__(self):
        return self
    def __next__(self):
        self.__a,  self.__b = self.__b,  self.__a+self.__b
        if self.__a > self.__end:
            self.__a, self.__b = 0, 1
            raise StopIteration
        return self.__a
        
        
        
for _ in FNumbers(20):
    print(_)
(2) 执行fib_numbers.py
可以直接在PyCharm中执行dog.py,点击run菜单下面的run子菜单。也可以进入命令行,切换到D:\Python3-Learning\chapter16,然后执行python fib_numbers.py。脚本程序运行成功以后,会看到下面的输出:
1
1
2
3
5
8

16.8.4 知识要点

(1) 在Python中,一切皆对象,只要在类中定义了__iter__方法,那么该类型就是可迭代的类型
(2) 定义__iter__方法只是表示当前类型可以迭代,但具体的迭代逻辑还需要在__next__方法中进行定义

16.8.5 最具实力的小班培训

薯条老师在广州做Python和Java的小班培训,一个班最多10人。不在广州的同学可以报名线上直播班,跟线下小班的同学们同步学习。打算参加小班培训的同学,必须遵守薯条老师的学习安排,认真做作业和项目。把知识学好,学扎实,那么找到一份高薪的工作就是很简单的一件事。

(1) Python后端工程师高薪就业班,月薪11K-18K,免费领取课程大纲
(2) Python爬虫工程师高薪就业班,年薪十五万,免费领取课程大纲
(3) Java后端开发工程师高薪就业班,月薪11K-20K, 免费领取课程大纲
(4) Python大数据分析,量化投资就业班,月薪12K-25K,免费领取课程大纲

扫码免费领取Python学习资料:


关注微信公众号.jpg












欢迎 发表评论:

请登录

忘记密码我要注册

注册账号

已有账号?请登录