1、迭代器对象的创建

迭代器是一种可以被遍历的对象,并且能够作用于next()函数,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能往后遍历,不能回溯。不像列表,你随时可以取后面的数据,也可以返回头取前面的数据,迭代器通常要实现两个基本方法next()iter()

概括的说,一个对象实现了__iter__()__next__()方法,那么它就是一个迭代器对象。

但是只实现了__iter__()方法没有实现__next__()方法,就只是一个可迭代对象。

例如:

  1. # 3.6之前的版本是不需要带.abc的,3.7就会提示需要加.abc
  2. from collections.abc import Iterable, Iterator
  3. class IterA:
  4. def __iter__(self):
  5. # 我们这里返回一个列表
  6. return [1, 2, 3]
  7. class IterB:
  8. pass
  9. iterA = IterA()
  10. iterB = IterB()
  11. # 可以看到iterA 是一个可迭代对象
  12. # iterB 是一个不可迭代对象
  13. print(isinstance(iterA, Iterable)) # True
  14. print(isinstance(iterB, Iterable)) # False
  15. # iterA是一个可迭代对象,但并不是一个迭代器对象
  16. # 因为IterA类中并没有实现next方法
  17. print(isinstance(iterA, Iterator)) # False

我们在IterA类中实现__next__()方法,IterA类就变成了一个迭代器对象了。

  1. # 3.6之前的版本是不需要带.abc的,3.7就会提示需要加.abc
  2. from collections.abc import Iterable, Iterator
  3. class IterA:
  4. def __iter__(self):
  5. # 我们这里返回一个列表
  6. return [1, 2, 3]
  7. def __next__(self):
  8. pass
  9. iterA = IterA()
  10. # 可以看到iterA 是一个可迭代对象
  11. # iterB 是一个不可迭代对象
  12. print(isinstance(iterA, Iterable)) # True
  13. # iterA对象也是要给迭代器对象
  14. print(isinstance(iterA, Iterator)) # True

2、实际应用案例

  1. """
  2. 1.迭代器的应用场景
  3. 1).如果数列的数据规模巨大
  4. 2).数列有规律,但是依靠列表推导式描述不出来
  5.  
  6. 2.数学中有个著名的斐波那契数列(Fibonacci),
  7. 数列中第⼀个数0,第⼆个数1,其后的每⼀个数都可由前两个数相加得到:
  8. 如下:
  9. 0,    1,    1,   2,    3,    5,   8,    13,    21,   34,    ...
  10. 现在我们想要通过for...in...循环来遍历迭代斐波那契数列中的前n个数。
  11. 那么这个斐波那契数列我们就可以⽤迭代器来实现,
  12. 每次迭代都通过数学计算来⽣成下⼀个数。
  13. """
  14. from collections.abc import Iterable, Iterator
  15. class FibIterator(object):
  16. """
  17. fib数列迭代器
  18. """
  19. # 初始化方法
  20. def __init__(self, count):
  21. # 斐波拉契数列中的前两个数
  22. self.num1 = 0
  23. self.num2 = 1
  24. # 用来保存迭代的总次数
  25. self.count = count
  26. # 用来记录迭代次数(计数器)
  27. self.i = 0
  28. # 实现__iter__表示FibIterator是一个可迭代对象
  29. # 返回对象自己。是一个可迭代对象
  30. def __iter__(self):
  31. return self
  32. # 实现__next__方法,是FibIterator定义为迭代器对象的重要条件之一
  33. def __next__(self):
  34. # 判断是否迭代结束,如果没有到达迭代次数,则返回数据
  35. # self.count 需要迭代的次数
  36. # self.i已迭代次数
  37. if self.i < self.count:
  38. item = self.num1
  39. # 计算num1, num2的值,方便下次迭代返回
  40. # 这里运用的是序列的封包与解包,不会的可以看我以前的文章(元组)
  41. self.num1, self.num2 = self.num2, self.num1 + self.num2
  42. # 执行一次next方法,计数器+1
  43. self.i += 1
  44. # 返回新获得的数,
  45. # 也就是前两个数求和的第三个数
  46. return item
  47. else:
  48. # 到达了迭代次数,抛出异常
  49. raise StopIteration
  50. # 创建一个fib数列迭代器对象
  51. fibIter = FibIterator(15)
  52. # fibIter对象是一个迭代器
  53. print(isinstance(fibIter, Iterable)) # True
  54. print(isinstance(fibIter, Iterator)) # True
  55. # 转换为列表查看fib对象内容
  56. # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
  57. print(list(fibIter))
  58. # 遍历,可执行
  59. for li in fibIter:
  60. print(li)

3、总结:

(1)整理总结

  • 对象是否实现了__iter__方法,如果实现了,该对象就是一个可迭代对象。
  • 一个对象实现了__iter__()__next__()方法,那么它就是一个迭代器对象。
  • 可以使用iter()函数把可迭代对象(Iterable)变成迭代器对象(Iterator)。
  • 通过isinstance()函数,可以判断一个对象是否是Iterable对象或者是Iterator对象。
    1. print(isinstance(fibIter, Iterable))
    2. print(isinstance(fibIter, Iterator))

(2)迭代协议

当任何可迭代对象传入到for循环或其他迭代工具中进行遍历时,迭代工具都是先通过iter()函数获得与可迭代对象对应的迭代器,然后再对迭代器调用next()函数,不断的依次获取元素,并在捕捉到StopIteration异常时,确定完成迭代,这就是完整的迭代过程,这也称之为“迭代协议”。

(3)为什么任何Python序列都可迭代?

  1. 都实现了__getitem__方法
  2. 标准序列也都实现了__iter__方法
  3. 实现了__getitem__方法,而且其参数是从0开始的索引,这种对象也可迭代,但它不是一个可迭代对象。

    原因是:如果没有实现__iter__方法,但实现了__getitem__方法,__getitem__()方法可以通过iter()函数转成Iterator,即可以在for循环中使用,按顺序(从0开始)获取元素。
    1. from collections.abc import Iterable, Iterator
    2. class IterObj:
    3. def __init__(self):
    4. self.a = [3, 5, 7, 11, 13, 17, 19]
    5. def __getitem__(self, i):
    6. return self.a[i]
    7. # 从创建对象
    8. it = IterObj()
    9. print(isinstance(it, Iterable)) # false
    10. print(isinstance(it, Iterator)) # false
    11. # <__main__.IterObj object at 0x0000000002573AC8>
    12. print(it)
    13. # # <iterator object at 0x10b231278>
    14. print(iter(it))
    15. # 遍历
    16. for i in it:
    17. print(i)

归纳:

  • 如果这个可迭代对象要在for循环中被使用,那么它就应该能够被内置的iter()函数调用并转化成Iterator对象。
  • Python的for语法功能非常强大,可以遍历任何可迭代的对象。

参考:

『无为则无心』Python基础 — 62、Python中自定义迭代器的更多相关文章

  1. 『无为则无心』Python基础 — 3、搭建Python开发环境

    目录 1.Python开发环境介绍 2.Python解释器的分类 3.下载Python解释器 4.安装Python解释器 5.Python解释器验证 1.Python开发环境介绍 所谓"工欲 ...

  2. 『无为则无心』Python基础 — 4、Python代码常用调试工具

    目录 1.Python的交互模式 2.IDLE工具使用说明 3.Sublime3工具的安装与配置 (1)Sublime3的安装 (2)Sublime3的配置 4.使用Sublime编写并调试Pytho ...

  3. 『无为则无心』Python基础 — 6、Python的注释

    目录 1.注释的作用 2.注释的分类 单行注释 多行注释 3.注释的注意事项 4.什么时候需要使用注释 5.总结 提示:完成了前面的准备工作,之后的文章开始介绍Python的基本语法了. Python ...

  4. 『无为则无心』Python基础 — 7、Python的变量

    目录 1.变量的定义 2.Python变量说明 3.Python中定义变量 (1)定义语法 (2)标识符定义规则 (3)内置关键字 (4)标识符命名习惯 4.使用变量 1.变量的定义 程序中,数据都是 ...

  5. 『无为则无心』Python基础 — 10、Python字符串的格式化输出

    目录 1.什么是格式化输出 2.Python格式化输出的五种方式 方式一:字符串之间用+号拼接 方式二:print()函数可同时输出多个字符串 方式三:占位符方式 方式四:f格式化方式(推荐) 方式五 ...

  6. 『无为则无心』Python基础 — 12、Python运算符详细介绍

    目录 1.表达式介绍 2.运算符 (1)运算符的分类 (2)算数运算符 (3)赋值运算符 (4)复合赋值运算符 (5)比较运算符 3.逻辑运算符 拓展1:数字之间的逻辑运算 拓展2:Python中逻辑 ...

  7. 『无为则无心』Python基础 — 44、对文件和文件夹的操作

    目录 1.os模块介绍 2.查看os模块相关文档 3.os模块常用方法 (1)文件重命名 (2)删除文件 (3)创建文件夹 (4)删除文件夹 (5)获取当前目录 (6)改变默认目录 (7)获取目录列表 ...

  8. 『无为则无心』Python基础 — 61、Python中的迭代器

    目录 1.迭代的概念 2.迭代器的概念 3.可迭代的对象(Iterable) 4.迭代器对象(Iterator) 5.迭代器的使用体验 (1)基本用法 (2)实际应用 1.迭代的概念 (1)什么是迭代 ...

  9. 『无为则无心』Python序列 — 24、Python序列的推导式

    目录 1.列表推导式 (1)快速体验 (2)带if的列表推导式 (3)多个for循环实现列表推导式 2.字典推导式 (1)创建一个字典 (2)将两个列表合并为一个字典 (3)提取字典中目标数据 3.集 ...

  10. 『无为则无心』Python函数 — 29、Python变量和参数传递

    目录 1.Python的变量 (1)Python变量不能独立存在 (2)变量是内存中数据的引用 (3)注意点 2.了解变量的引用 3.Python的参数传递(重点) (1)示例 (2)结论 (3)总结 ...

随机推荐

  1. 【刷题-PAT】A1108 Finding Average (20 分)

    1108 Finding Average (20 分) The basic task is simple: given N real numbers, you are supposed to calc ...

  2. JUC之线程池的实现原理以及拒绝策略

    线程池实现原理 向线程池提交任务后,线程池如何来处理这个任务,之前我们了解了7个参数,我们通过这些参数来串联其线程池的实现原理. 1.在创建了线程池后,开始等待请求 2.当调用execute()方法添 ...

  3. Windows和Linux关闭占用端口

    关闭端口的方式有很多种,但是常用的就是这种比较来的快一点 如果通过以下方式解决不了,可以通过关闭服务来解决 Windows 1.查看端口占用的进程 netstat -ano | findstr 800 ...

  4. WebGPU 中消失的 VAO

    1 VAO 是 OpenGL 技术中提出来的 参考: 外链 其中有一段文字记录了 VAO 是什么: A Vertex Array Object (VAO) is an object which con ...

  5. golang中http编程

    1. http server package main import ( "fmt" "net/http" ) func main() { // 请求url和对 ...

  6. Python小练习-购物商城(一部分代码,基于python2.7.5)

    新手写作,用来练习与提高python编写.思考能力,有错误的地方请指正,谢谢! 第一次写博客,课题是一位大神的博客,本着练习的目的,就自己重写了一遍,有很多不足的地方,希望借博客记录下自己的成长:  ...

  7. ARTS Week 22

    Algorithm 本周的 LeetCode 题目为 297. 二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也 ...

  8. 返回值Student-Json

    MyController中 index.jsp 修改url

  9. Servlet-base标签的作用(相对路径和绝对路径)

    Web中的相对路径和绝对路径 在javaWeb中,路径分为相对路径和绝对路径: 相对路径: .     表示当前目录 .. 表示上一级目录 资源名 表示当前目录/资源名 绝对路径: http://ip ...

  10. 集合框架-ListIterator接口

    1 package cn.itcast.p4.list.demo; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 imp ...