迭代器(Iterable)和for..in..的三种协议

一。迭代器协议

1.  迭代器协议:对象需要提供next方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代

2. 可跌达对象:实现了迭代器协议的对象

3. 协议是一种约定,可迭代对象实现迭代器协议,在Python中,迭代是通过for ... in来完成的

二。简单迭代器

以斐波那契数列为例,写一个简单的迭代器

>>> from collections import Iterable
>>> class Fib:
...     def __init__(self):
...         self.a,self.b = 0,1
...     def __iter__(self):
...         return self
...     def next(self):
...         self.a,self.b = self.b,self.a + self.b
...         if self.a > 100:
...             raise StopIteration()
...         return self.a
...
>>> a = Fib()
>>> for n in a:
...     print n
...
1
1
2
3
5
8
13
21
34
55
89
>>> isinstance(a,Iterable)
True
>>> 

Fib既是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(因为实现了__next__方法)

再简化一下,不用for....in....

>>> a = Fib()
>>> it = iter(a)
>>> next(it)
1
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> 

一个迭代器只迭代一次,重复跌代要获得新的迭代器。

三。for...in... 协议

1.   协议A: __iter__ + next

这是迭代器的协议,和上面说的一样,for..in.. 先调用iter(a) 让a的__iter__返回一个迭代器,然后循环这个迭代器的next方法直到没有下一个元素异常退出。

for...in... 首先执行跌达器,比如存在跌达和__getitem__就会以跌达器遍历.

2.  协议B: __getitem__

>>> class B:
...     def __getitem__(self,n):
...         print n
...         time.sleep(2)
...         return ‘a‘
...
>>> b = B()
>>> for x in b:
...     print x
...
0
a
1
a
2
a
3
a
4

n 一直循环的增长,直到有异常此循环才退出,一般作为下标索引遍历

>>> class B:
...     def __init__(self):
...         self.l = [‘a‘,‘b‘,‘c‘,‘d‘,‘e‘]
...     def __getitem__(self,n):
...         return self.l[n]
...
>>> b = B()
>>> for x in b:
...     print x
...
a
b
c
d
e
>>> 

3.  协议C: yield关键字

>>> def c():
...     yield ‘a‘
...     yield ‘b‘
...     yield ‘c‘
...     yield ‘d‘
...
>>> c1 = c()
>>> print next(c1),next(c1),next(c1),next(c1),next(c1)
a b c d
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> 

这是生成器(generator),是可迭代对象,不是一次性列出结果,用到了才按照某种规则得出结果,占用内存很少,用for...in...时不断循环调用 next() 方法,每次 next() 后 yield 返回一个值并挂起,到下次 next() 从上次挂起的 yield 接着执行,yield 和 return 一样返回值,生成器只迭代一次,因为没有__iter__返回新的迭代对象。

时间: 2024-10-23 00:07:56

迭代器(Iterable)和for..in..的三种协议的相关文章

UART、I2C、SPI三种协议对比

学嵌入式需要打好基础 下面我们来学习下计算机原理里的3种常见总线协议及原理 协议:对等实体之间交换数据或通信所必须遵守规则或标准的集合 1.UART(Universal Asynchronous Receiver/Transmitter): 通用异步接收发送器,也就是通常所说的串口,基本都用于调试 三根线:RX.TX.GND 如果甲是PC机,B是单片机,两者还要接一块电平转换芯片,用于将TTL / CMOS(单片机电平)转换为RS232(PC机电平).因为TTL / CMOS电平范围是0?1.8

SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)

SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART(Universal Asynchronous Receiver Transmitter:通用异步收发器) 第二,区别在电气信号线上: SPI总线由三条信号线组成:串行时钟(SCLK).串行数据输出(SDO).串行数据输入(SDI).SPI总线可以实现多个SPI设备互相连接.提供SPI串行时钟的SPI

RDP/SSH/VNC三种文件传输协议有什么区别?

客户端和终端主机之间的文件交互我们称之为文件传输.在主机运维过程中,我们常常需要进行文件传输,以确保网站能够正常运行.不同系统的服务器使用的文件传输协议不同,文件传输的方式也不尽相同.那么文件传输协议都有哪些?目前市面上主流的文件传输工具有哪些?RDP文件传输协议:RDP远程协议是一个多通道协议,让用户通过本地电脑连接远程服务器.大部分的Windows.Linux服务器都有相应的客户端. 行云管家基于B/S架构(Browser/Server,浏览器/服务器模式)设计,直接使用浏览器远程连接服务器

迭代器三种遍历方法

迭代器三种遍历方法,其中也有listIterator在遍历中加入新的元素,不会报错 1 /* 2 listIterator 方法有双向遍历的特点 3 如果要在迭代的过程中加入新的元素,那么就需要利用迭代器中的it.add()方法; 4 不能使用list.add()方法! 5 */ 6 //三种遍历list容器的方式 7 List list = new ArrayList(); 8 list.add("xiaoming"); 9 list.add("longge");

数据结构 《22》---- 二叉树三种遍历的迭代器算法

二叉树的三种遍历有递归版本,和迭代版本.本文介绍一种新的思路. 参考了 http://coolshell.cn/articles/9886.html 在许多应用中,我们还需要对遍历本身进行抽象.假如有一个求和的函数sum,我们希望它能应用于链表,数组,二叉树等等不同的数据结构.这时,我们可以抽象出迭代器(Iterator)的概念,通过迭代器把算法和数据结构解耦了,使得通用算法能应用于不同类型的数据结构. 以下给出了三种遍历的迭代器算法. class Iterator { public: virt

List遍历三种方法:1.for 2.增强性for 3.迭代器

package chapter09; import java.util.ArrayList;import java.util.Iterator;import java.util.List; /* * List遍历三种方法:1.for 2.增强性for 3.迭代器 */public class TestList { public static void main(String[] args) { // 声明一个集合 List list = new ArrayList(); String aStri

谈谈vector容器的三种遍历方法

说明:本文仅供学习交流,转载请标明出处,欢迎转载! vector容器是最简单的顺序容器,其使用方法类似于数组,实际上vector的底层实现就是采用动态数组.在编写程序的过程中,常常会变量容器中的元素,那么如何遍历这些元素呢?本文给出三种遍历方法. 方法一:采用下标遍历 由于vector容器就是对一个动态数组的包装,所以在vector容器的内部,重载了[]运算符,函数原型为:reference operator [] (size_type n);所以我们可以采用类似于数组的方式来访问vector容

Java中List集合遍历的三种方式

首先创建一个List集合: List<String> list = new ArrayList<String>();list.add("name"); list.add("age"); list.add("sex"); 第一种:利用集合的size()方法遍历for(int i= 0:i<list.size();i++){ list.get(i);} 第二种:for增强循环for(String string : str

三种形式遍历集合

对于遍历集合获取其对象,在这里总结的三种简单的方式 方式一 : 将集合变为数组,后遍历数组 Object[] obj = list.toArray(); for(Object s : obj){ System.out.println((String) s); } 方式二 :  get()方法获取 . 但只能在list集合中使用, 只有List集合才有索引值. for(int i = 0;i<list.size();i++){ System.out.println(list.get(i)); }