Python迭代器

名称前后加两个下划线,__name__,这种名字组成的集合所包含的方法称为特殊方法,这些方法会在特殊情况下被Python调用,无需直接调用它们。

特殊方法:构造方法

------------------------------------------------------------------------------------

创建一个对象时,构造方法已经执行过一次了,例如f=FooBar()

def __init__(self,value=43):       //参数为可选参数

  xxxx

f=FooBar()            //创建方式一

f=FooBar('this is a constructor')     //创建方式二

--------------------------------------------------------------------------------------

构造方法被重写时,子类调用超类方法:

1.调用超类构造方法的未绑定版本(旧版本)

class SongBird(Bird):

  def __init__(self):

    Bird.__init__(self)     //调用超类构造方法的未绑定版本

    self.sound=...

  def ...

2.使用super函数(新版)

_metaclass_=type    //新版python的标志

class SongBird(Bird):

  def __init__(self):

    super(SongBird.self).__init__()     //调用超类方法

    self.sound=...

  def ...

----------------------------------------------------------------------------------------

序列(列表,元祖等)和映射(字典)是对象的集合。

特殊方法:

__len__(self)  :返回序列中的个数,或映射中键-值对的数量。若为0,则返回假值

__getitem__(self,key) : 返回键对应的值,序列中键为0->n-1,集合中键为任何种类的键

__setitem__(self,key,value) : 存储key和value,只能为可以修改的对象定义这个方法

__delitem__(self,key) : 使用del语句时被调用

----------------------------------------------------------------------------------------

迭代器:

Python的内置工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象(对象需要提供next方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代)

迭代工具   迭代对象 满足如下之一的都是可迭代对象
for,sum,min,max 列表,元祖,字典,字符串,文件对象

1.可以for循环: for i in iterable
2.可以按index索引的对象,也就是定义了__getitem__方法,比如list,str;
3.定义了__iter__方法。可以随意返回。
4.可以调用iter(obj)的对象,并且返回一个iterator

 

 

生成器表达式

[x * x for x in numbers]

{x * x for x in numbers}{1, 4, 36, 9, 16, 25}

{x: x * x for x in numbers}

lazy_squares = (x * x for x in numbers)

是---> 生成器 是--->

迭代器

x=iter(y)

任何具有__next__()方法的对象都是迭代器

是--->

 

可迭代对象y

可迭代的类中,一般实现以下两个方法,

__iter__()以及__next()__方法,

__iter__()方法返回self

<---是

列表,元祖,字典,文件对象以及管道对象

表达式(容器)

生成器方法

包含yield参数的函数

是---> <---通过iter()方法变成

任意对象

(只要返回一个迭代器)

       

 

     

 

                 
                 
可迭代对象:x=[1,2,3] 变成迭代器:y=iter(x) 迭代取值:next(y)            
  相当于 for i in x:            
                 
                 
                 

 例如列表x=[1,2],是可迭代的(因为它实现了迭代器协议),但是它不是迭代器,执行i=iter(x)后, 变成了迭代器,j=i.next()  -->  1 ,j=i.next()    -->  2,     i.next()引发StopIteration异常

    for j in x:  (for循环使用迭代器协议访问对象,自动调用迭代器的next()方法,并监视StopInteration异常)

 

 如何定义一个可迭代对象?或者说为什么list,dict,str等就是可迭代的?迭代器协议是什么?

可迭代对象就是实现了迭代器协议的对象

迭代器协议是指对象必须提供一个next方法和iter()方法,next方法中定义返回迭代的下一项和引起一个StropIteration的异常,以终止迭代。

(字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,调用了他们内部的iter方法,把他们变成了可迭代对象 
然后for循环调用可迭代对象的next方法去取值,而且for循环会捕捉StopIteration异常,以终止迭代

 

如何定义一个迭代器?

生成器就是自定义的迭代器?

itertools模块:

包含各种迭代器

------------------------------------------------------

for,sum,min,max等迭代工具可以作用于可迭代对象上,可迭代对象就是实现了迭代协议的对象,即内部定义了iter()和next()方法的对象,例如列表、元祖、字典、字符串、文件对象等,这些序列对象内部都定义了iter()和next()方法。为什么定义一个列表x=[1,2],没有x.next()方法呢?因为字符串、列表、元祖、字典、集合、文件对象这些都不是可迭代对象,只不过在for循环中,调用了他们内部的iter方法,把他们变成了可迭代对象。然后for循环调用可迭代对象的next方法去取值,而且for循环会捕捉StopIteration异常,以终止迭代。

例子::::::

x=[1,2]

#一:下标访问方式

print(x[0])

print(x[1])

#print(x[2]) 超出边界报错:IndexError

 

#二:遵循迭代器协议访问方式

x1=x.__iter__()

print(x1.__next__())

print(x1.__next__())

#print(x1.__next__()) 超出边界报错:StopIteration

 

#三:for循环访问方式

#for循环本质就是遵循迭代器协议的访问方式,先调用x1=x.__iter__()方法,或者直接x1=iter(x),然后依次执行x1.next(),直到for循环捕捉到StopIteration终止循环

#for循环所有对象的本质都是一样的原理

for i in x:    #x1=x.__iter__()

     print(i)    #i=x1.next()

 

#四:用while去模拟for循环做的事情

x1=x.__iter__()

while True:

      try:

            print(x1.__next__())

      except StopIteration:

             print("")

              break

for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的iter方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象都可以通过for循环来遍历了。

 

生成器:可以理解为一种数据类型,这种数据类型自动实现了迭代器协议,生成器就是可迭代对象。其他的数据类型需要调用自己内置的iter方法。

由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且在没有值可以返回的时候,生成器自动产生StopIteration异常

创建生成器:

方法一、生成器函数-与常规函数一样,只不过用yield代替return,yiled语句属于挂起的状态,以便之后从它离开的地方继续执行,更省内存

方法二、生成器表达式

方法一:

import sys

def fibonacci(n):

    a,b,counter=0,1,0

    while True:

         if(counter>n):

               return

          yield a

          a,b=b,a+b

          counter+=1

f=fibonacci(10)

while True:

      try:

           print next(f)

       except StopIteration:

            sys.exit()

方法二:

1.列表解析的[]换成()得到的就是生成器表达式,只不过生成器表达更节省内存

选自:http://blog.csdn.net/u010350925/article/details/73431058

posted @ 2017-11-17 14:06  eudaemonia  阅读(175)  评论(0编辑  收藏  举报