python基础学习笔记(十一)

系统 1580 0

python基础学习笔记(十一)

2013-05-14 23:31  虫师 阅读( ... ) 评论( ... ) 编辑 收藏

 

 

迭代器

 

本节进行迭代器的讨论。只讨论一个特殊方法 ---- __iter__   ,这个方法是迭代器规则的基础。

 

迭代器规则

迭代的意思是重复做一些事很多次 --- 就像在循环中做的那样。 __iter__  方法返回一个迭代器,所谓迭代器就是具有 next 方法的对象,在调用 next 方法时,迭代器会返回它的下一个值。如果 next 方法被调用,但迭代器没有值可以返回,就会引发一个 StopIteration 异常。

 

这里是一个婓波那契数例,使用迭代器如下:

                
                  class
                
                
                   Fibs:
    
                
                
                  def
                
                
                  __init__
                
                
                  (self):
        self.a 
                
                =
                
                   0
        self.b 
                
                = 1
    
                
                  def
                
                
                   next(self):
        self.a , self.b 
                
                = self.b , self.a +
                
                   self.b
        
                
                
                  return
                
                
                   self.a
    
                
                
                  def
                
                
                  __iter__
                
                
                  (self):
        
                
                
                  return
                
                
                   self


                
                >>> fibs =
                
                   Fibs() 

                
                >>> 
                
                  for
                
                 f 
                
                  in
                
                
                   fibs:
      
                
                
                  if
                
                  f  > 1000
                
                  :
          
                
                
                  print
                
                
                   f
          
                
                
                  break
                
                
                  #
                
                
                  因为设置了break ,所以循环在这里停止。
                
                

1597
              

内建函数 iter 可以从可迭代的对象中获得迭代器。

                >>> it = iter([1,2,3
                
                  ])

                
                >>>
                
                   it.next()

                
                1
>>>
                
                   it.next()

                
                2
              

 

从迭代器得到序列

除了在迭代器和可迭代对象上进行迭代外,还能把它们转换为序列。在大部分能使用序列的情况下,能使用迭代器替换。

                
                  class
                
                
                   TestIterator:
    value 
                
                =
                
                   0
    
                
                
                  def
                
                
                   next(self):
        self.value 
                
                += 1
        
                
                  if
                
                 self.value > 10: 
                
                  raise
                
                
                   StopIteration
        
                
                
                  return
                
                
                   self.value
    
                
                
                  def
                
                
                  __iter__
                
                
                  (self):
        
                
                
                  return
                
                
                   self


                
                >>> ti =
                
                   TestIterator()

                
                >>>
                
                   list(ti)
[
                
                1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
              

 

生成器

 

生成器也叫 简单生成器,生成器可以帮助读者写出非常优雅的代码,当然,编写任何程序时不使用生成器也是可以的。

 

创建生成器

创建一个生成器就像创建函数一样简单。

                >>> 
                
                  def
                
                
                   flatten(nested):
    
                
                
                  for
                
                 sublist 
                
                  in
                
                
                   nested:
        
                
                
                  for
                
                 element 
                
                  in
                
                
                   sublist:
            
                
                
                  yield
                
                
                   element

            

                
                >>> nested = [[1,2],[3,4],[5
                
                  ]]

                
                
                  #
                
                
                  使用for循环
                
                
>>> 
                
                  for
                
                 num 
                
                  in
                
                
                   flatten(nested):
    
                
                
                  print
                
                
                   num

    

                
                1
2
3
4
5

                
                  #
                
                
                  或使用list函数
                
                
>>>
                
                   list(flatten(nested))
[
                
                1, 2, 3, 4, 5]
              

 

递归生成器

上面创建的生成器只能处理两层嵌套,为了处理嵌套使用了两个 for 循环,如果要处理任意层的嵌套呢?例如,可以每层嵌套需要增加一个 for 循环,但不知道有几层嵌套,所以必须把解决方案变得更灵活,现在可以用递归来解决。

                >>> 
                
                  def
                
                
                   fla(aa):
    
                
                
                  try
                
                
                  :
        
                
                
                  for
                
                 bb 
                
                  in
                
                
                   aa:
            
                
                
                  for
                
                 cc 
                
                  in
                
                
                   fla(bb):
                
                
                
                  yield
                
                
                   cc
    
                
                
                  except
                
                
                   TypeError:
        
                
                
                  yield
                
                
                   aa


                
                >>> list(fla([[[1],2],3,4,[5,[6,7]],8]))  
                
                  #
                
                
                  注意括号层次比较多
                
                
[1, 2, 3, 4, 5, 6, 7, 8]
              

fla 被调用时有两种情况: 基本情况和需要递归的情况

  在基本的情况中,函数被告知展开一个元素,这种情部下, for 循环会引发一个 TypeError  异常,生成会产生一个元素。

  如果展开的是一个列表,那么就需要特殊情况处理。程序必须遍历所有的子列表,并对它们调用 fla

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

上面的做法有一个问题:如果 aa  是一个类似于字符串的对象(字符串、 Unicode UserString 等),那么它就是一个序列,不会引发 TypeError ,但是你不想对这样的对象进行迭代。

为了处理这种情况,则必须在生成器的开始处添加一个检查语句。试着将传入的对象和一个字符串拼接,看看会不会出现 TypeError ,这是检查一个对象是不是类似于字符串最简单快速的方法。

                >>> 
                
                  def
                
                
                   flatten(nested):
    
                
                
                  try
                
                
                  :
       
                
                
                  #
                
                
                  不要迭代类似字符串的对象
                
                
                  try
                
                :nested + 
                
                  ''
                
                
                  except
                
                 TypeError: 
                
                  pass
                
                
                  else
                
                : 
                
                  raise
                
                
                   TypeError
        
                
                
                  for
                
                 sublist 
                
                  in
                
                
                   nested:
            
                
                
                  for
                
                 element 
                
                  in
                
                
                   flatten(sublist):
                
                
                
                  yield
                
                
                   element
    
                
                
                  except
                
                
                   TypeError:
        
                
                
                  yield
                
                
                   nested

        

                
                >>> list(flatten([
                
                  '
                
                
                  foo
                
                
                  '
                
                ,[
                
                  '
                
                
                  bar
                
                
                  '
                
                ,[
                
                  '
                
                
                  baz
                
                
                  '
                
                
                  ]]]))
[
                
                
                  '
                
                
                  foo
                
                
                  '
                
                , 
                
                  '
                
                
                  bar
                
                
                  '
                
                , 
                
                  '
                
                
                  baz
                
                
                  '
                
                ]
              

如果 nested+ ’’  引发了一个 TypError  ,它就会被忽略。如果没有引发 TypeError ,那么内层 try 语句就会引发一个它自己的 TypeError 异常。

 

 

生成器方法

生成器新属性是在开始运行后为生成器提供值的能力。表现为生成器和“外部世界”进行交流的渠道:

  *  外部作用域访问生成器的 send 方法,就像访问 next  方法一样,只不过前者使用一个参数(发送的“消息” --- 任意对象)

  *  在内部则挂起生成器, yield 现在作为表达式而不是语句使用,换句话说,当生成器重新运行的时候, yield 方法返回一个值,也就是外部通过 send 方法发送的值。如果 next  方法被使用,那么 yield 方法返回 None. 

下面简单的方例子来说明这种机制:

                >>> 
                
                  def
                
                
                   repeater(value):
    
                
                
                  while
                
                
                   True:
        new 
                
                =(
                
                  yield
                
                
                   value)
        
                
                
                  if
                
                 new 
                
                  is
                
                
                  not
                
                 None:value =
                
                   new

        

                
                >>> r = repeater(42
                
                  )

                
                >>>
                
                   r.next()

                
                42
>>> r.send(
                
                  "
                
                
                  hello, world!
                
                
                  "
                
                
                  )

                
                
                  '
                
                
                  hello, world!
                
                
                  '
                
              

生成器的另两个方法:

  * throw 方法(使用异常类型调用,还有可选的值以及回溯对象)用于在生成器内引发一个异常(在 yield 表达式中)

  * close  方法(调用时不用参数)用于停止生成器。

 

 


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论