zoukankan      html  css  js  c++  java
  • 装饰器和单例模式

    一、装饰器

      装饰器本质就是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。装饰器的应用场景:插入日志,性能测试,事务处理,缓存等场景

      二、装饰器的形成过程

      现在有个需求,想让你测试这个函数的执行时间,在不改变这个函数的情况下。

      1,简单版装饰器

     
    import time
    def fun():
        time.sleep(2)
        print('你好啊')
    
    def test(f):
        def inner():
            start_time=time.time()
            f()
            end_time=time.time()
            print(end_time-start_time)
        return inner
    fun=test(fun)          #这个版本的虽然可以实现任何功能的测试,但每次函数执行前都得写上这一句很是麻烦
    fun()

      2,语法糖

     
    import time
    def fun():
        time.sleep(2)
        print('你好啊')
    
    def test(f):
        def inner():
            start_time=time.time()
            f()
            end_time=time.time()
            print(end_time-start_time)
        return inner
    @test           #相当于fun=test(fun),只是里面封装好了的,以后测试函数就不用写fun=test(fun),只需要在定义函数上面写上@test就行
    fun()
     

      上面的装饰器装饰的函数都没有参数,下面装饰一个带参数的装饰器。

      3,装饰带参数的函数

     
    import time
    def test(f):
        def inner(*args,**kwargs):
            start_time=time.time()
            f(*args,**kwargs)
            end_time=time.time()
            print(end_time-start_time)
        return inner
    @test
    def fun():
        time.sleep(2)
        print('你好啊')

      4,装饰带参数和有返回值的函数

     
    import time
    def test(f):
        def inner(*args,**kwargs):
            start_time=time.time()
            res=f(*args,**kwargs)
            end_time=time.time()
            print(end_time-start_time)
            return res
        return inner
    @test
    def fun1(a,s,d,f):
        return a+s+d+f

       对于上面的装饰器来说,如果我要看函数的信息,比如fun.__doc__查看函数注释的方法,fun.__name__查看函数名,由于加上装饰器后fun=inner,所以结果会有错误。下面解决

      5,可以查看函数信息的装饰器

     
    import time
    from functools import wraps
    def test(f):
        @wraps(f)
        def inner(*args,**kwargs):
            start_time=time.time()
            res=f(*args,**kwargs)
            end_time=time.time()
            print(end_time-start_time)
            return res
        return inner
    @test
    def fun1(a,s,d,f):
        return a+s+d+f
     

      三、装饰器主要功能和固定结构

      1,固定写法

    复制代码
    def timer(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            re = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return re
        return inner
     

      2,可以查看函数信息的

     
    from functools import wraps
    
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
     

      四、带参数的装饰器(是装饰器袋参数)

      比如说之前要求你为10个函数加上装饰,你得在每个函数上面写上@;一个月之后,不需要装饰器了,你又要把每个函数上的@给去掉;没过多久又让你加上装饰器;反复添加,反复删除,这可是10万个函数,很庞大的工程。其实现在给装饰器加一个参数,很轻松就解决问题。

     
    import time
    def outer(flg):
        def test(f):
            def inner(*args,**kwargs):
                if flg:
                    start_time=time.time()
                res=f(*args,**kwargs)
                if flg:
                    end_time=time.time()
                    print(end_time-start_time)
                return res
            return inner
        return test
    flg=True       #flg为True时加上装饰器,为False时不加装饰器
    @outer(flg)
    def fun1(a,s,d,f):
        return a+s+d+f
    r=fun1(2,3,4,5)
    print(r)
     

      五、多个装饰器装饰一个函数

     
    def wrapper1(func):  func=f
        def inner1():
            print('wrapper1 ,before func')
            func()
            print('wrapper1 ,after func')
        return inner1
    
    def wrapper2(func):  func=inner1
        def inner2():
            print('wrapper2 ,before func')
            func()
            print('wrapper2 ,after func')
        return inner2
    
    @wrapper2     #f=wrapper2(f),现在后面的f已经变为inner1,f=inner2
    @wrapper1     #f=wrapper1(f),f=inner1
    def f():
        print('in f')
    
    f()      #此时f为inner2
    所以结果为:
    wrapper2,before func
    wrapper1,before func
    in f
    wrapper1,after func
    wrapper2,after func
     

      六、单例模式

      单例模式就是一个类只能产生一个对象,就算产生多个对象,多个对象都是指向同一地址

     
    class Person:
        __status=None
        def __new__(cls, *args, **kwargs):
            if not Person.__status:
                Person.__status=object.__new__(Person)
            return Person.__status
    ob1=Person()
    ob2=Person()
    print(ob1)
    print(ob2)
     
  • 相关阅读:
    HDU_1042——阶乘,万进制
    HDU_2136——最大质因数,素数筛选法
    POJ_1321——棋盘问题,回溯+剪枝
    POJ_3009——冰球,IDS迭代加深搜索
    STL_vector
    比较长的文章进行分页显示
    winform中comboBox控件加默认选项的问题
    生成日期随机码
    删除dataGridview中选中的一行或多行
    SQl 事务增加数据
  • 原文地址:https://www.cnblogs.com/lowen107/p/10247070.html
Copyright © 2011-2022 走看看