装饰器总结
前提
使用装饰器的前提在于Python提供的特性:
- 函数即对象,可以进行传递;
- 函数可以被定义在另外一个函数中;
可以通过一个例子来了解:
def get_animal(name=‘dog‘): def dog(): return ‘this is a dog‘ def cat(): return ‘this is a cat‘ # 返回函数对象 if name == ‘dog‘: return dog elif name == ‘cat‘: return cat else: return ‘other animal‘ animal = get_animal(‘cat‘) print(animal) # <function get_animal.<locals>.cat at 0x104b30d90> print(animal())
注意:其返回的并不是调用函数,而是返回函数对象,只有在函数对象后面加上括号才表明要进行调用对象。
装饰器
装饰器就是可以在原来函数的基础上增加其它的功能,而不改变原函数本身。
如何写一个装饰器呢,下面给出一个基础的模版:
def my_decorator(a_function_to_decorate): def wapper_function(*args, **kwargs): print(‘Before the function runs‘) a_function_to_decorate(*args, **kwargs) print(‘After the function runs‘) return wapper_function @my_decorator def stand_function(): print(‘stand function runs‘) stand_function()
执行结果为:
Before the function runsstand function runsAfter the function runs
如果要求原函数的信息不变,那么可以使用functools.wraps
,其本身也是一个装饰器,作用是将原函数的名称、模块、文档字符串等拷贝到装饰器里面的fun函数中,例子如下:
# "functools" 可以改变这点 import functools def bar(func): @functools.wraps(func) def wrapper(): return func() return wrapper
需要注意的问题是:
- 如果有多个装饰器的时候,则由里到外装饰,也就是按照距离函数的位置谁越近越就被装饰。
- 在装饰器的基础上还可以进行装饰,比如装饰装饰器的装饰器。
最后写一个题目,写一个decorator,在函数开始和结束时增加log,并且统计函数执行时间,保留原函数名:
import logging, time def create_logger(): logger = logging.getLogger("example_logger") logger.setLevel(logging.INFO) # create the logging file handler handler = logging.FileHandler(r"./test.log") formatter = logging.Formatter(‘%(asctime)s - %(name)s - %(levelname)s - %(message)s‘) handler.setFormatter(formatter) # add handler to logger object logger.addHandler(handler) return logger def exception(logger): def decorator(func): def wrapper(*args, **kwargs): start = time.time() try: logger.info(‘function runs‘) res = func(*args, **kwargs) print(‘the function used time: {}‘.format(time.time()-start)) logger.info(‘function stops‘) return res except: # log the exception err = "There was an exception in " err += func.__name__ logger.exception(err) raise Exception return wrapper return decorator logger = create_logger() @exception(logger=logger) def foo(name=‘foo_function‘): print(‘i am {}‘.format(name)) return True print(foo())
运行结果如下:
i am foo_functionthe function used time: 0.0008778572082519531True
logger中的结果如下:
2017-08-15 03:25:59,234 - example_logger - INFO - function runs2017-08-15 03:25:59,235 - example_logger - INFO - function stops
时间: 2024-12-13 19:01:32