Day05

作者: G流殇 | 来源:发表于2018-06-08 00:30 被阅读0次

    一、装饰器进阶

    多个装饰器同时装饰一个函数,执行顺序是由上往下执行被装饰函数执行之前的操作,再执行被装饰函数,最后再由下往上执行被装饰函数执行之后的操作。

    二、列表生成式,迭代器&生成器

    2.1 列表生成式

    生成一个含有数字1-10的列表,并且每个数字要 * 2

    # 1.循环
    li = []
    for i in range(1, 11):
        li.append(i * 2)
    print(li)
    
    

    代码简洁的列表生成式

    # 2.列表生成式
    li2 = [i * 2 for i in range(1, 11)]
    print(li2)
    
    

    for循环后面还可以加上if判断

    # 3.for循环后面还可以加上if判断
    li3 = [i * i for i in range(1, 11) if i % 2 == 0]   # 生成1-10的平方切且可以被2整除的列表
    print(li3)
    
    

    2.2 generator生成器

    在Python中,这种一边循环一边计算的机制,称为生成器:generator。

    2.2.1 生成器特性
    1. 生成器只有在调用时才会生成相应的数据。
    2. 只记录当前的位置。
    3. 只有一个__next__()方法。(2.7为next()
    2.2.1 创建生成器

    创建一个generator,有很多种方法。
    第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

    >>> l = [x * x for x in range(10)]
    >>> l
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> g = (x * x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x000002256EAB2E60>
    
    

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

    >>> next(g)
    0
    >>> next(g)
    1
    >>> next(g)
    4
    >>> next(g)
    9
    >>> next(g)
    16
    >>> next(g)
    25
    >>> next(g)
    36
    >>> next(g)
    49
    >>> next(g)
    64
    >>> next(g)
    81
    >>> next(g)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    
    

    但不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

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

    通过for循环来迭代generator,不需要关心StopIteration的错误。
    generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
    比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:1, 1, 2, 3, 5, 8, 13, 21, 34, ...

    def fib(max):
       n, a, b = 0, 0, 1
       while n < max:
           print(b)
           a, b = b, a + b
           n = n + 1
       return 'done'
    
    

    可以输出斐波那契数列的前N个数:

    >>> fib(10)
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    done
    
    

    上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

    def fib(max):
       n, a, b = 0, 0, 1
       while n < max:
           #print(b)
           yield  b
           a, b = b, a + b
           n += 1
    
    

    同样的,把函数改成generator后,可以使用__next__()来获取下一个返回值,或者使用for循环来迭代。
    通过yield实现在单线程的情况下实现并发运算的效果

    import time
    def customer(name):
       print("%s 准备吃包子了!" % name)
       while True:
           baozi = yield
           print("包子[%s]来了,被[%s]吃了!" % (baozi, name))
    
    def producer(name):
       c = customer('A')
       c2 = customer('B')
       c.__next__()
       c2.__next__()
       print("%s要开始做包子了啊!" % name)
       for i in range(10):
           time.sleep(1)
           print("第%d批包子做好了!" % (i + 1))
           c.send(i + 1)
           c2.send(i + 1)
    
    producer("Will")
    
    

    三、迭代器

    3.1 Iterable可迭代对象

    可以直接作用于for循环的数据类型有以下几种:

    1. 集合数据类型,如list、tuple、dict、set、str等;
    2. generator:包括生成器和带yield的generator function。
      这些可以直接作用于for循环的对象统称为可迭代对象:Iterable
      可以使用isinstance()判断一个对象是否是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
    
    

    3.2 Iterator迭代器

    生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
    可以使用isinstance()判断一个对象是否是Iterator对象:

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

    3.3 将Iterable可迭代对象变为Iterator迭代器

    生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
    把list、dict、str等Iterable变成Iterator可以使用iter()函数:

    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True
    
    

    四、匿名函数

    匿名函数就是不需要显式的指定函数

    #这段代码
    def calc(n):
        return n**n
    print(calc(10))
    
    #换成匿名函数
    calc = lambda n:n**n
    print(calc(10))
    
    

    匿名函数主要是和其它函数搭配使用的

    >>> res = map(lambda x:x**2, [1, 5, 7, 4, 8])
    >>> for i in res:print(i)
    ... 
    1
    25
    49
    16
    64
    
    

    五、内置函数

    image.png

    相关文章

      网友评论

          本文标题:Day05

          本文链接:https://www.haomeiwen.com/subject/llxosftx.html