装饰器:装饰你的梦

装饰你的梦

一、不用装饰器

为函数增加计时

def deco(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print(end_time - start_time)


def myfunc():
    time.sleep(0.6)

deco(myfunc)

二、封装一层

def deco(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print(end_time - start_time)
    return wrapper

def myfunc():
    time.sleep(0.6)

myfunc = deco(myfunc)
myfunc()

三、装饰器语法糖


def deco(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print(end_time - start_time)
    return wrapper

@deco
def myfunc():
    time.sleep(0.6)

myfunc()

使用了”@”语法糖后,我们就不需要额外代码来给”myfunc”重新赋值了,其实”@deco”的本质就是”myfunc=deco(myfunc)”,当认清了这一点后,后面看带参数的装饰器就简单了。

四、被装饰的函数带参数

def deco(func):
    def wrapper(a, b):
        start_time = time.time()
        func(a, b)
        end_time = time.time()
        print(end_time - start_time)
    return wrapper

@deco
def myfunc(a, b):
    print("a + b =", a+b)
    time.sleep(0.6)

myfunc(10, 9)

五、被装饰的函数带参数

这里还有一个问题,如果多个函数拥有不同的参数形式,怎么共用同样的装饰器?在Python中,函数可以支持(*args, **kwargs)可变参数,所以装饰器可以通过可变参数形式来实现内嵌函数的签名。


def deco(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
    return wrapper

@deco
def myfunc(a, b):
    print("a + b =", a+b)
    time.sleep(0.6)

myfunc(10, 9)

使用位置和关键字参数可以兼容各种函数,装饰器就成了通用的了。

使用了*args位置参数和**kwargs关键字参数,不明白先补下知识点。

六、被装饰函数有返回值

def deco(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
        return res
    return wrapper

@deco
def myfunc(a, b):
    time.sleep(0.6)
    return a+b

res = myfunc(10, 9)
print(res)

七、装饰器也想带参数

功能:装饰器里的计时功能可以关闭

def deco(arg=True):
    if arg:
        def _deco(func):
            def wrapper(*args, **kwargs):
                start_time = time.time()
                func(*args, **kwargs)
                end_time = time.time()
                print(end_time - start_time)
            return wrapper
    else:
        def _deco(func):
            return func
    return _deco

@deco(arg=False)        # 这里注意下, @deco(arg=False)先执行,就变形成了@_deco(func)
def myfunc(a, b):
    print("a + b =", a+b)
    time.sleep(0.6)

myfunc(10, 9)

又封装一层,好多层!

八、多个装饰器

离函数近的优先执行

def deco_1(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
    return wrapper


def deco_2(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print("from deco_2:")
    return wrapper

@deco_1
@deco_2
def myfunc(a, b):
    print("a + b =", a+b)
    time.sleep(0.6)

myfunc(10, 9)

参考:

http://www.cnblogs.com/linhaifeng/articles/7532497.html#_label5
http://python.jobbole.com/82344/
原文地址:https://www.cnblogs.com/wualin/p/9795819.html