zoukankan      html  css  js  c++  java
  • 装饰器函数 迭代器函数 生成器函数

    装饰器函数

    装饰器的主要功能:在不改变函数调用方式的基础上在函数的前、后添加功能。

    装饰器的固定格式:

    #装饰器定式
    #例子1:
    def wrapper(func):
    def inner(*args,**kargs):
    ret = func(*args,**kargs)
    return ret
    return inner

    @wrapper #语法糖 可用代替 qqxing =wrapper(qqxing)
    def qqxing():
    print(123)
    ret = qqxing() #相当于执行inner
    -----------------------------------------------------------
    #例子2:
    import time
    def wrapper(func):         #装饰器函数,f是被装饰的函数
    def inner(*args,**kwargs):
    #在被装饰函数之前要做的事
    ret = func(*args,**kwargs) #被装饰的函数
    #在被装饰函数之后要做的事
    return ret
    return inner
    @wrapper #语法糖
    def func(a,b):
    time.sleep(0.01)
    print("你好",a,b)
    func("小黑","小白")

    带参数的装饰器

    
    
    #假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?
    # 一个一个的取消掉? 没日没夜忙活3天。。。
    # 过两天你领导想通了,再让你加上。。。

    #方法一:
    #适用少量装饰器,每次需要更改每一个语法糖后面的变量值,比较麻烦。第二种是进阶方法
    def outer(flag):
        def timer(func):
            def inner(*args,**kwargs):
                if flag:
                    print('''执行函数之前要做的''')
                re = func(*args,**kwargs)
                if flag:
                    print('''执行函数之后要做的''')
                return re
            return inner
        return timer
    
    @outer(False)        #在语法糖后面加一个布尔值,当需要执行装饰器内部的函数就写成True,否则False
    def func():
        print(111)
    func()
    -------------------------------------------------------------------
    #方法二:
    #是第一种方法的进阶版,只需要更改FLAG变量就可以控制所有的装饰器是否执行,适用于写了很多的装饰器
    import time
    FLAG=False         #只需要改变FLAG的变量 
    def outer(flag):
    def timmer(func):
    def inner(*args,**kwargs):
    if flag:
    start = time.time()
    ret =func(*args,**kwargs)
    end=time.time()-start
    print(end)
    return ret
    else:
    ret =func(*args,**kwargs)
    return ret
    return inner
    return timmer

    @outer(FLAG)
    def ceshi():
    time.sleep(0.2)
    print('测试成功')
    ceshi()

    @outer(FLAG)
    def ceshi2():
    time.sleep(0.3)
    print('测试成功')
    ceshi2()

     多个装饰器装饰同一个函数

    def wrapper1(func):
        def inner():
            print('wrapper1 ,before func')
            func()
            print('wrapper1 ,after func')
        return inner
    
    def wrapper2(func):
        def inner():
            print('wrapper2 ,before func')
            func()
            print('wrapper2 ,after func')
        return inner
    
    @wrapper2
    @wrapper1
    def f():
        print('in f')
    f()

    #结果:

    wrapper2 ,before func
    wrapper1 ,before func
    in f
    wrapper1 ,after func
    wrapper2 ,after func

    执行过程:

     

    迭代器函数 

    可迭代与迭代器的区别

    可迭代:在Python中如果一个对象有__iter__( )方法或__getitem__( )方法,则称这个对象是可迭代的(Iterable);其中__iter__( )方法的作用是让对象可以用for ... in循环遍历,__getitem__( )方法是让对象可以通过“实例名[index]”的方式访问实例中的元素。换句话说,两个条件只要满足一条,就可以说对象是可迭代的。显然列表List、元组Tuple、字典Dictionary、字符串String等数据类型都是可迭代的。当然因为Python的“鸭子类型”,我们自定义的类中只要实现了__iter__( )方法或__getitem__( )方法,也是可迭代的

    迭代器:在Python中如果一个对象有__iter__( )方法和__next__( )方法,则称这个对象是迭代器(Iterator);其中__iter__( )方法是让对象可以用for ... in循环遍历,__next__( )方法是让对象可以通过next(实例名)访问下一个元素。注意:这两个方法必须同时具备,才能称之为迭代器。列表List、元组Tuple、字典Dictionary、字符串String等数据类型虽然是可迭代的,但都不是迭代器,因为他们都没有next( )方法。

    生成器函数 

    #只含有yeild关键字的函数是生成器函数
    #yeild不能和return共用且需要写在函数内部
    def generate():
    print(1)
    yield 'a'
    #生成器函数:执行之后会得到一个生成器作为返回值
    g=generate() #g就是生成器
    print(g)
    ret=g.__next__()
    print(ret)

    #结果:
    <generator object generate at 0x037F1F70>
    1
    a
    #生产两百万件衣服
    def closes():
        for i in range(200):
            yield'close%s'%i
    g=closes()
    for i in range(20):
        ret=g.__next__()
        print(ret)
    for i in range(20):
        ret = g.__next__()
        print(ret)

     生成器函数进阶:

    def generate():
        print(123)
        content=yield
        print('====',content)
        print(456)
        yield 2
    
    g=generate()
    ret=g.__next__()
    print(ret)
    ret = g.send('hello')      #send获取下一个值的效果和next效果一致                #只是在获取下一个值的时候,给上一个yield的位置传递一个数据
    print(ret) 

    #结果:
    123
    None
    ==== hello
    456
    2

    #使用send的注意事项:
      #第一个使用生成器的时候,是用next获取下一个值
      #最后一个yield不能接受外部的值
    #获取移动平均值
    def average():
        sum=0
        count=0
        avg=0
        while True:
            num=yield avg
            sum =sum+num
            count=count+1
            avg=sum/count

    生成器表达式和列表推导式

    egg_list=[]                #for循环
    for i in  range(10):
        egg_list.append("鸡蛋%s"%i)
    print(egg_list)
    
    egg_list=['鸡蛋%s'%i for i in range(10)]#列表推导式
    print(egg_list)
    #生成器表达式
    g=(i for i in range(10))
    print(g)
    for i in g:
        print(i)
    
    g=(i*i for i in range(10))
    print(g)
    for i in g:
        print(i)

    #[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理
    #[满足条件的元素相关的操作 for 元素 in 可迭代的数据类型 if 元素相关的条件 ] #筛选功能 #30以内所有能被3整除的数 ret
    =[i for i in range(30) if i%3==0] print(ret) #30以内所有能被3整除的数的平方 ret=[i*i for i in range(30) if i%3==0] print(ret) #找出嵌套列表中名字含有两个'e'的所有名字 names =[['hhhh','rrr','hhhh','eettr','tryee'],['sfsgg','eerfgsg','gertfre','atarw','sarar']] ret=[name for lst in names for name in lst if name.count('e')==2] print(ret)

    面试题:

    #面试题
    def add(n,i):
        return n+i
    
    def test():
        for i in range(4):
            yield i
    
    g=test()
    for n in [1,10]:
        g=(add(n,i) for i in g)
    
    n=1
    g = (add(n, i) for i in g)
    n=10
    g = (add(n, i) for i in (add(n, i) for i in g))
    print(list(g))
  • 相关阅读:
    第十七讲:解释器模式
    第十六讲:适配器模式
    第十五讲:桥接模式
    第十四讲:组合模式
    第十三讲:外观模式
    第十二讲:代理模式
    第十一讲:享元模式
    第九讲:策略模式
    工厂模式
    观察者设计模式
  • 原文地址:https://www.cnblogs.com/yzcstart/p/10580844.html
Copyright © 2011-2022 走看看