zoukankan      html  css  js  c++  java
  • python迭代器,生成器,列表生成式

    列表生成式

    列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。

    例如:

    >>> [x * x for x in range(1, 11)]
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    

    生成器

    1.定义

    一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器

    2.作用

    这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。

    另外,还可通过yield实现在单线程的情况下实现并发运算的效果

    例如1 :保存中断状态

    def cash_out(amount):
        while amount > 0:
            amount -= 1
            yield 1
        return "done"
    
    
    ATM = cash_out(5)
    try:
        print("取到钱 %s 万" % ATM.__next__())
        print("花掉花掉!")	
        print("取到钱 %s 万" % ATM.__next__())
        print("取到钱 %s 万" % ATM.__next__())
        print("花掉花掉!")
        print("取到钱 %s 万" % ATM.__next__())
        print("取到钱 %s 万" % ATM.__next__())
        print("取到钱 %s 万" % ATM.__next__())  # 到这时钱就取没了,再取就报错了
        print("取到钱 %s 万" % ATM.__next__())
    except StopIteration as e:
        print("%s" %e.value)
    #输出结果
    取到钱 1 万
    花掉花掉!
    取到钱 1 万
    取到钱 1 万
    花掉花掉!
    取到钱 1 万
    取到钱 1 万
    done
    
    

    例如2:单线程进行并发运算

    import time
    
    
    def consumer(name):
        print("%s 准备吃包子啦!" % name)
        while True:
            baozi = yield
    
            print("包子[%s]来了,被[%s]吃了!" % (baozi, name))
            
    def producer(name):
        c = consumer('A')
        c2 = consumer('B')
        c.__next__()
        c2.__next__()
        print("老子开始准备做包子啦!")
        for i in range(10):
            time.sleep(1)
            print("做了2个包子!")
            c.send(i)
            c2.send(i)
            
    producer("alex")
    

    3.返回值

    yield是生成器返回值

    return返回值是StopIterator错误抛出的值

    迭代器

    1.特点

    1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
    2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
    3. 访问到一半时不能往回退
    4. 便于循环比较大的数据集合,节省内存
    >>> a = iter([1,2,3,4,5])
    >>> a
    <list_iterator object at 0x101402630>
    >>> a.__next__()
    1
    >>> a.__next__()
    2
    >>> a.__next__()
    3
    >>> a.__next__()
    4
    >>> a.__next__()
    5
    >>> a.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    2.常见的迭代器

    py3

    #range使用了迭代器,每次需要获取才调用函数
    >>> range(10)
    range(0, 10)
    #文件读取的时候,read()和readlines()将所有内容都读取到列表,会占用大量内存
    #使用迭代器,一行行的读和操作,性能更优
    f = open("1.txt")
    for i in f:
          print(i)
    

    py2

    >>> range(10)
    [0,1,2,3,4,5,6,7,8,9]
    
    >>> xrange(10)
    range(0, 10)
    

    3.可迭代对象

    一类是集合数据类型,如listtupledictsetstr等;

    一类是generator,包括生成器和带yield的generator function。

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

    >>> from collections import Iterable
    >>> isinstance([], Iterable)
    True
    >>> isinstance({}, Iterable)
    True
    >>> isinstance('abc', Iterable)
    True
    >>> isinstance((x for x in range(10)), Iterable)
    True
    >>> isinstance(100, Iterable)
    False
    

    为什么listdictstr等数据类型不是Iterator

    这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

    Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

    listdictstrIterable变成Iterator可以使用iter()函数:

    #list dict string不是迭代器
    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False
    
    #list dict string可以转换为迭代器
    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True
    
  • 相关阅读:
    使用json-lib进行Java和JSON之间的转换
    ajax+json+java
    了解Json
    Ehcache RIM
    利用FreeMarker静态化网页
    Timer和TimerTask
    windows下memcache安装
    mac下安装YII
    php static 和self区别
    YII behaviors使用
  • 原文地址:https://www.cnblogs.com/akiz/p/11144306.html
Copyright © 2011-2022 走看看