• python基础列表生成式,迭代器


    1 >>> L = [x * x for x in range(10)]
    2 >>> L
    3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    4 >>> g = (x * x for x in range(10))
    5 >>> g
    6 <generator object <genexpr> at 0x1022ef630>

    列表生成式和生成器generator,可以通过next()函数获得generator的下一个返回值。generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

    获取迭代器里面的内容正确的方法是通过for循环。并且不会报错。

    >>> g = (x * x for x in range(10))
    >>> for n in g:
    ...     print(n)
    ...
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81

    generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

    比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

    1, 1, 2, 3, 5, 8, 13, 21, 34, ...

    斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

     1 def fib(max):
     2     n, a, b = 0, 0, 1
     3     while n < max:
     4         print(b)
     5         a, b = b, a + b
     6         n = n + 1
     7     return 'done'
     8 >>> fib(10)
     9 1
    10 1
    11 2
    12 3
    13 5
    14 8
    15 13
    16 21
    17 34
    18 55
    19 done

    上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了,并定义f=fib(6),f就是个生成器。同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代。但是此方法拿不到函数最终的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中:

     1 >>> g = fib(6)
     2 >>> while True:
     3 ...     try:
     4 ...         x = next(g)
     5 ...         print('g:', x)
     6 ...     except StopIteration as e:
     7 ...         print('Generator return value:', e.value)
     8 ...         break
     9 ...
    10 g: 1
    11 g: 1
    12 g: 2
    13 g: 3
    14 g: 5
    15 g: 8
    16 Generator return value: done

    此处需要练习写代码:还可通过yield实现在单线程的情况下实现并发运算的效果:

     1 #_*_coding:utf-8_*_
     2 __author__ = 'Alex Li'
     3 
     4 import time
     5 def consumer(name):
     6     print("%s 准备吃包子啦!" %name)
     7     while True:
     8        baozi = yield
     9 
    10        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
    11 
    12 
    13 def producer(name):
    14     c = consumer('A')
    15     c2 = consumer('B')
    16     c.__next__()
    17     c2.__next__()
    18     print("老子开始准备做包子啦!")
    19     for i in range(10):
    20         time.sleep(1)
    21         print("做了2个包子!")
    22         c.send(i)
    23         c2.send(i)
    24 
    25 producer("alex")

    概念部分:

    1.直接作用于for循环的数据类型有以下几种:一是集合数据类型,如listtupledictsetstr等;二是是generator,包括生成器和带yield的generator function。

    2.Iterable可迭代对象:可以直接作用于for循环的对象。isinstance()判断一个对象是否是Iterable对象

     1 >>> from collections import Iterable
     2 >>> isinstance([], Iterable)
     3 True
     4 >>> isinstance({}, Iterable)
     5 True
     6 >>> isinstance('abc', Iterable)
     7 True
     8 >>> isinstance((x for x in range(10)), Iterable)
     9 True
    10 >>> isinstance(100, Iterable)
    11 False

    3.迭代器Iterator*可以被next()函数调用并不断返回下一个值的对象称为迭代器。可以使用isinstance()判断一个对象是否是Iterator对象。


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

    1 >>> isinstance(iter([]), Iterator)
    2 True
    3 >>> isinstance(iter('abc'), Iterator)
    4 True

    小结

    凡是可作用于for循环的对象都是Iterable类型;

    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

    集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

    Python的for循环本质上就是通过不断调用next()函数实现的,例如:

    for x in [1, 2, 3, 4, 5]:
        pass
    
    
    #等价于
    
    # 首先获得Iterator对象:
    it = iter([1, 2, 3, 4, 5])
    # 循环:
    while True:
        try:
            # 获得下一个值:
            x = next(it)
        except StopIteration:
            # 遇到StopIteration就退出循环
            break
  • 相关阅读:
    (33)ElasticSearch文档的核心元数据解析
    (32)ElasticSearch的容错机制
    (31)ElasticSearch水平扩容的过程
    (30)ElasticSearch两个节点环境中创建index解析
    (29)ElasticSearch分片和副本机制以及单节点环境中创建index解析
    UVA
    HDU
    ZOJ
    BZOJ1499: 瑰丽华尔兹(单调队列)
    UVALive
  • 原文地址:https://www.cnblogs.com/letgo-doo/p/8459912.html
Copyright © 2020-2023  润新知