装饰器

from datetime import datetime

一个小例子

def alan():
    print('alan speaking')

alan()

同时输出今天的时间

def alan():
    print('alan speaking')
    date = datetime.utcnow()
    print(date)

alan()

tom()、john()、Mary()也要输出类似句子

def date(func):
    func()
    date = datetime.utcnow()
    print(date)

def alan():
    print('alan speaking')

def tom():
    print('tom speaking')

date(tom)

要实现直接调用alan()或者tom()就可以输出结果,又要避免重复写相同的代码,只需要在定义tom以后调用tom之前,加上tom= date(tom)

def date(func):
    def wrapper():
        func()
        date = datetime.utcnow()
        print(date)
    return wrapper

def alan():
    print('alan speaking')

def tom():
    print('tom speaking')

tom = date(tom)
tom()

这也就是装饰器的概念,可以通过@语法使用

def date(func):
    def wrapper():
        func()
        date = datetime.utcnow()
        print(date)
    return wrapper

@date
def alan():
    print('alan speaking')
@date
def tom():
    print('tom speaking')

tom()

装饰器带参数

def pre_date(pre):
    def date(func):
        def wrapper():
            func()
            date = datetime.utcnow()
            print(pre  + str(date))
        return wrapper
    return date

@pre_date('Today is :')
def alan():
    print ('alan speaking')

@pre_date('I am Tom :')
def tom():
    print ('tom speaking')

alan()

保留原函数基本信息,例如函数名、函数文档等
可以通过使用Python自带模块functools中的wraps来保留函数的元信息

import functools

def date(func):
    @functools.wraps(func)
    def wrapper():
        func()
        date = datetime.utcnow()
        print(date)
    return wrapper

@date
def alan(content):
    print('alan speaking')
@date
def tom():
    """ddde"""
    print('tom speaking')

tom()

print(tom.__name__)
print(tom.__doc__)

原函数带参数

def date(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        date = datetime.utcnow()
        print(date)
    return wrapper

@date
def alan():
    print('alan speaking')
@date
def tom(content):
    print('tom speaking', content)

tom("I'm tom")

使用装饰器捕获异常

def date(func):
    def wrapper():
        try:
            func()
        except Exception as e:
            print(e)
        date = datetime.utcnow()
        print(date)
    return wrapper

@date
def alan():
    print('alan speaking')
@date
def tom():
    print('tom speaking')
    print(5/0)

tom()

使用装饰器捕获异常,完整版

def except_decorator(func):
    def wrapper(*args, **kwargs):
        try:
            func(*args, **kwargs)
        except Exception as e:
            print('exception fun: ',func.__name__)
            print(e)
        date = datetime.utcnow()
        print(date)
    return wrapper

@except_decorator
def tom(content):
    print('tom speaking', content)
    print(5/0)

tom("I'm tom")

在类中使用装饰器

class A(object):
    def date(func):
        def wrapper(self):
            func(self)
            date = datetime.utcnow()
            print(date)
        return wrapper


    @date
    def alan(self):
        print('alan speaking')
    @date
    def tom(self):
        print('tom speaking')

a = A()
a.alan()

在类中使用装饰器,原函数带参数

class A(object):
    def date(func):
        def wrapper(self, *args, **kwargs):
            func(self, *args, **kwargs)
            date = datetime.utcnow()
            print(date)
        return wrapper


    @date
    def alan(self, content):
        print('alan speaking', content)
    @date
    def tom(self):
        print('tom speaking')

a = A()
a.alan("I'm tom")