zoukankan      html  css  js  c++  java
  • python生成器

    迭代器是一个对象,而生成器是一个函数,迭代器和生成器是python中两个非常强大的特性,编写程序时你可以不使用生成器达到同样的效果,但是生成器让你的程序更加pythonic。创建生成器非常简单,只要在函数中加入yield语句即可。函数中每次使用yield产生一个值,函数就返回该值,然后停止执行,等待被激活,被激活后继续在原来的位置执行。下边的例子实现了同样的功能:

     1 #!/usr/bin/env python  
     2 #coding=utf-8  
     3 def fib():  
     4     a,b = 0,1  
     5     while 1:  
     6         a,b = b,a+b  
     7         yield a  
     8 for f in fib():  
     9     if f < 10000:  
    10         print (f) 
    11     else:  
    12         break  
    13 
    14 
    15 1
    16 1
    17 2
    18 3
    19 5
    20 8
    21 13
    22 21
    23 34
    24 55
    25 89

    如何迭代?

        根本上说, 迭代器就是有一个 next() 方法的对象, 而不是通过索引来计数. 当你或是一个循环机制(例如 for 语句)需要下一个项时, 调用迭代器的 next() 方法就可以获得它. 条目全部取出后, 会引发一个 StopIteration 异常, 这并不表示错误发生, 只是告诉外部调用者, 迭代完成.

        不过, 迭代器也有一些限制. 例如你不能向后移动, 不能回到开始, 也不能复制一个迭代器.如果你要再次(或者是同时)迭代同个对象, 你只能去创建另一个迭代器对象. 不过, 这并不糟糕,因为还有其他的工具来帮助你使用迭代器. 

        reversed() 内建函数将返回一个反序访问的迭代器. enumerate() 内建函数同样也返回迭代器.另外两个新的内建函数, any() 和 all() , 在 Python 2.5 中新增, 如果迭代器中某个/所有条目的值都为布尔真时,则它们返回值为真. 本章先前部分我们展示了如何在 for 循环中通过索引或是可迭代对象来遍历条目. 同时 Python 还提供了一整个 itertools 模块, 它包含各种有用的迭代器.

    迭代器工作原理
       如果这是一个实际应用程序, 那么我们需要把代码放在一个 try-except 块中. 序列现在会自 
    动地产生它们自己的迭代器, 所以一个 for 循环: 

    for i in seq:  
        do_something_to(i)

    实际上是这样工作的:

    fetch =  seq.__iter__
    #iter(seq)
    while True:
        try:
            i = fetch.next()
        except StopIteration:
            break
    do_something_to(i)

    另外, Python 还引进了三个新的内建字典方法来定义迭代: myDict.iterkeys() (通过 keys 迭 

    代), myDict.itervalues() (通过 values 迭代), 以及 myDicit.iteritems() (通过 key/value 对来迭代). 注意, in 操作符也可以用于检查字典的 key 是否存在 , 之前的布尔表达式myDict.has_key(anyKey) 可以被简写为 anyKey in myDict .

    ===文件===

        文件对象生成的迭代器会自动调用 readline() 方法. 这样, 循环就可以访问文本文件的所有
    行. 程序员可以使用 更简单的 for eachLine in myFile 替换 for eachLine in myFile.readlines() :

    >>>myFile=open(‘config-win.txt’)  
      
    >>> for eachLine in myFile:  
    … print eachLine, # comma suppresses extra n  
    …  
    [EditorWindow]  
    font-name: courier new  
    font-size: 10  
    >>> myFile.close()  

    可变对象和迭代器

        记住,在迭代可变对象的时候修改它们并不是个好主意. 这在迭代器出现之前就是一个问题.
    一个流行的例子就是循环列表的时候删除满足(或不满足)特定条件的项:

    for eachURL in allURLs:  
        if not eachURL.startswith(‘http://’):  
            allURLs.remove(eachURL) # YIKES!! 

    除列表外的其他序列都是不可变的, 所以危险就发生在这里. 一个序列的迭代器只是记录你当前到达第多少个元素, 所以如果你在迭代时改变了元素, 更新会立即反映到你所迭代的条目上.在迭代字典的 key 时, 你绝对不能改变这个字典. 使用字典的 keys() 方法是可以的, 因为keys() 返回一个独立于字典的列表. 而迭代器是与实际对象绑定在一起的, 它将不会继续执行下去:

    myDict = {'a': 1, 'b': 2, 'b': 3, 'd': 4}  
    for eachKey in myDict:
        print (eachKey, myDict[eachKey])
        del myDict[eachKey] 
    
    '''
    结果:
    d 4
    Traceback (most recent call last):
      File "test.py", line 2, in <module>
        for eachKey in myDict:
    RuntimeError: dictionary changed size during iteration
    '''

    这样可以避免有缺陷的代码. 更多有关迭代器的细节请参阅 PEP 234 .

    如何创建迭代器

    对一个对象调用 iter() 就可以得到它的迭代器. 它的语法如下:

    iter(obj)  
    iter(func, sentinel)  

    如果你传递一个参数给 iter() , 它会检查你传递的是不是一个序列, 如果是, 那么很简单: 
    根据索引从 0 一直迭代到序列结束. 另一个创建迭代器的方法是使用类, 我们将在第 13 章详细 
    介绍, 一个实现了 __iter__() 和 next() 方法的类可以作为迭代器使用.

    如果是传递两个参数给 iter() , 它会重复地调用 func , 直到迭代器的下个值等于sentinel .

    公众号请关注:侠之大者
  • 相关阅读:
    Objective-C-----协议protocol,代码块block,分类category
    iOS-Core Data 详解
    TCP、UDP详解
    springboot+mybatisplus配置多个mapper路径
    django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb的解决方法
    Django笔记——Eclipse+pydev首个django例子helloworld
    eclipse html插件的下载和安装
    sqlserver往字符串里固定位置插入字符
    在文件夹中直接调用命令提示符
    HTML:如何将网页分为上下两个部分
  • 原文地址:https://www.cnblogs.com/kamil/p/5207258.html
Copyright © 2011-2022 走看看