zoukankan      html  css  js  c++  java
  • python之路4:各种器

    1. 装饰器

    2. 生成器

    3. 迭代器

     

    一、装饰器

    装饰器是函数,官方叫语法糖,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。 

    语法:  

    def wrapper(func):
        def result():
            print('before')
            func()
            print('after')
    
        return result
    
    
    @wrapper
    def foo():
        print('foo')
    

    实例:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # __author__ = 'lvlibing'
    
    import time
    
    def timer(func): #timer(test1)  func = test1
        def deco(*args,**kwargs):
            start_time = time.time()
            func(*args,**kwargs) #run test1()
            stop_time = time.time()
            print('the func run time is %s' %(start_time - stop_time))
        return deco
    
    @timer # test1 = timer(test1)
    def test1():
        time.sleep(1)
        print('in the test1')
    
    @timer # test2 =timer(test2) = deco test2(name) = deco(name)
    def test2(name,age):
        print('test2:',name,age)
    
    test1()
    test2('lv',22)
    

      

      

    二、生成器

    一边循环一边计算的机制,称为生成器:generator。

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

     

    1
    2
    3
    4
    5
    6
    >>> L = [x * for in range(10)]
    >>> L
    [0149162536496481]
    >>> g = (x * for in range(10))
    >>> g
    <generator object <genexpr> at 0x1022ef630>

    创建Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

    我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?

    如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值。

    如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。

    generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # __author__ = 'lvlibing'
    
    import time
    
    """
    '列表生成式'
    a = (x * x for x in range(100))
    print(a)
    
    for loop in a:
        print(loop)
        
    print(a.__next__())
    # print(a.__next__())
    # print(a.__next__())
    """
    #Fibonacci斐波那契数列
    def fibnaci(max):
        n,a,b = 0,0,1
        while n < max:
            #print(b) #会执行return,获得done返回值
            yield b #函数定义中包含yield关键字,此时函数将变成一个生成器,不会执行return
        #tuple = (b,a+b)
        # a,b = tuple[0],tuple[1]
            a,b = b,a+b
            n += 1
        return 'done'
    
    f=fibnaci(10)
    print(f)
    # print(f.__next__())
    '''
    for n in f:
        print(n)
        
    '''
    while True:
        try:
            t = next(f)
            print('f:',t)
        except StopIteration as e:
            print('Generator return value:', e.value)
            break
    
    #生产消费者模型,协程(生成器并行运算)
    def consumer(name):
        print('%s准备吃包子了'%name)
        while True:
            baozhi = yield
            print('包子[%s]来了,被[%s]吃了' %(baozhi,name))
    
    def producer(name1,name2):
        c1 = consumer(name1)
        c2 = consumer(name2)
        c1.__next__()
        c2.__next__()
        print('后厨开始准备做包子')
        for i in range(10):
            time.sleep(0.01)
            print('做了2个包子')
            c1.send(i)#send方法调用前面函数yiled
            c2.send(i)#send方法调用前面函数yiled
    
    producer('a','b')
    

      

     

    三、迭代器

    我们已经知道,可以直接作用于for循环的数据类型有以下几种:

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

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

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

    可以使用isinstance()判断一个对象是否是Iterable对象。

    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

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

    你可能会问,为什么listdictstr等数据类型不是Iterator

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

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

     

    小结

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

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

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

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # __author__ = 'lvlibing'
    
    from collections import Iterable
    from collections import Iterator
    
    print(isinstance((), Iterable))#T
    print(isinstance([], Iterable))#T
    print(isinstance({}, Iterable))#T
    
    print(isinstance({}, Iterator))#F
    print(isinstance([], Iterator))#F
    print(isinstance(iter([]), Iterator))#T
    print(isinstance(iter({}), Iterator))#T
    
    '''
    for x in [1,3,5,7,9]:
        pass
    等同
    it = iter([1,3,5,7,9])
    while True:
        try:
            x = next(it)
        except StopIteration:
            break
    '''
    

     

    参考: 

    http://www.cnblogs.com/alex3714

    http://www.cnblogs.com/wupeiqi

    internet&python books

    PS:如侵权,联我删。

     

  • 相关阅读:
    爬取校园新闻首页的新闻的详情,使用正则表达式,函数抽离
    网络爬虫基础练习
    Mysql 使用 select into outfile
    Mysql 使用CMD 登陆
    使用Clean() 去掉由函数自动生成的字符串中的双引号
    Get Resultset from Oracle Stored procedure
    获取引用某个主键的所有外键的表
    Entity Framework 丢失数据链接的绑定,在已绑好的EDMX中提示“Choose Your Data Connection”
    添加MySql Metat Database 信息
    at System.Data.EntityClient.EntityConnection.GetFactory(String providerString)
  • 原文地址:https://www.cnblogs.com/BillyLV/p/7052669.html
Copyright © 2011-2022 走看看